mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
210 Commits
main
...
v4.1.7.RELEASE
| Author | SHA1 | Date | |
|---|---|---|---|
| 261e37485a | |||
| 40fc260d45 | |||
| c4e0f14ec4 | |||
| 38b8262e1e | |||
| 9c3580d04e | |||
| a837cbe81f | |||
| f1b42b7d8f | |||
| 3d131c9f3c | |||
| a8ac6db43b | |||
| bf94344139 | |||
| b3f01998d2 | |||
| 8dd182f76c | |||
| b731f7ad15 | |||
| 9dea9d57db | |||
| c85127d3f8 | |||
| 846fae241b | |||
| d08c0669da | |||
| 13a2ae27e1 | |||
| ef9910c3c4 | |||
| 33b9bd72cc | |||
| bccdefdf30 | |||
| 2109db0c02 | |||
| 6f7ad3b1c0 | |||
| 84ae28b2bb | |||
| d2621baf0a | |||
| 7a6ce1c265 | |||
| 063a720ac0 | |||
| 3227007816 | |||
| daf12a9723 | |||
| b5bb26b7c6 | |||
| ae3cc67391 | |||
| 55de4a69ae | |||
| bf38b3a4fc | |||
| aa3a78aa0e | |||
| 6cdc208c73 | |||
| fd1b5e80a7 | |||
| 3c6f1f8352 | |||
| c111bd7547 | |||
| 1177f5c0a3 | |||
| bd05e3ade2 | |||
| bd601ce2e4 | |||
| 24783303a7 | |||
| 9e8e7aa6b9 | |||
| c99cc53da1 | |||
| cd9b58b0ab | |||
| ae35e84c1e | |||
| 391f72d2e4 | |||
| 633d13ffab | |||
| ca17dc06a5 | |||
| 51c941ca11 | |||
| 9e925aa86c | |||
| a899e066f2 | |||
| 89694b009a | |||
| a8f75399f8 | |||
| 14cd3ef2d5 | |||
| ce4e795f09 | |||
| 0cd7fed050 | |||
| 8e074b6b67 | |||
| 5b10575ce5 | |||
| 6a7aab02aa | |||
| e95a7a47c3 | |||
| fb7476f543 | |||
| 56f8d17b0c | |||
| 6783ba2903 | |||
| 8f6ac19f50 | |||
| e67a63e1f7 | |||
| f1dbe8db27 | |||
| bf423b2ca0 | |||
| 581cf3a0a5 | |||
| b44044e36f | |||
| 34a5fb28c2 | |||
| 50f49774bc | |||
| e799554ab8 | |||
| e2a55ced50 | |||
| 35bf96763d | |||
| fc79ea3dd7 | |||
| e9e2b7369e | |||
| 89f5248189 | |||
| d506767202 | |||
| d0a9bd0696 | |||
| 97f779674f | |||
| 5f6ae13002 | |||
| 52ed9b7106 | |||
| ca09eb2c59 | |||
| 13a87453b6 | |||
| 673dac5620 | |||
| 6892ad42d6 | |||
| 1d5128ed1b | |||
| 34aac078b1 | |||
| f52702ea3c | |||
| d2d006b68f | |||
| 8d14e7736a | |||
| 2de5faf56c | |||
| 5f95ff6bfd | |||
| 4446b5fe8a | |||
| 76649a4455 | |||
| 98d00ea698 | |||
| ce84fafde4 | |||
| b352dbfdeb | |||
| f42c53d9be | |||
| 151e96cac4 | |||
| a522fa36af | |||
| 5c463a1680 | |||
| 0280a2a994 | |||
| b455626ce1 | |||
| cb6459c271 | |||
| 6b9e89118f | |||
| f2b9a0a117 | |||
| 406adb3381 | |||
| bac012f3e8 | |||
| f93394171a | |||
| ebe45cf079 | |||
| 7ed7f981c9 | |||
| f01a0303f1 | |||
| f2691901bb | |||
| 5f305759fa | |||
| 410fc6d763 | |||
| 3783591083 | |||
| 1259671f3f | |||
| 590b23ccb3 | |||
| 2d98988d5c | |||
| 364210b0e7 | |||
| b6f22aa514 | |||
| 522c1b1b3d | |||
| 55eb5b622c | |||
| 6c93745f35 | |||
| ca9f6a1e1e | |||
| 3570a9a94a | |||
| 91c47a9eb8 | |||
| 7eb4679f28 | |||
| 0f95c81712 | |||
| 2c47098b35 | |||
| b4d9fb9e6e | |||
| 4a332bd0b2 | |||
| 772552b9ef | |||
| 6be554cba5 | |||
| ce085a606f | |||
| c0e550cfb4 | |||
| 7a5b2e6a75 | |||
| d7dcf8d6f4 | |||
| d77af71e9c | |||
| 5db4e4bab0 | |||
| 7cc56e1630 | |||
| b5e80390de | |||
| 55a14eb684 | |||
| d8269dd9fe | |||
| aae7583141 | |||
| 6fafe63311 | |||
| f1e406c63b | |||
| c8a4d1649f | |||
| 8dbe753963 | |||
| 23fa37b08b | |||
| cc78d40c6b | |||
| 1dc39324b9 | |||
| 2a240b0dc8 | |||
| 3b8d878285 | |||
| d98f626be1 | |||
| b8dbf2345c | |||
| 2b135f0d51 | |||
| e5d41d91d5 | |||
| f398dd03a7 | |||
| f82c6635d7 | |||
| 9499e4166c | |||
| bf442c093c | |||
| fab8dd3d0b | |||
| 1646f62700 | |||
| c8d9bfadad | |||
| 0706889222 | |||
| 25644dbdb9 | |||
| 181b35243e | |||
| 6c47b5f5d3 | |||
| 4a423e50a8 | |||
| 0225a7776c | |||
| d57f7f8783 | |||
| 4550b4a254 | |||
| f902fb911c | |||
| 77c8aa53ae | |||
| bb5da15e1c | |||
| 0c8d07fcff | |||
| 47fdac9214 | |||
| 7ffa845aa8 | |||
| 09bd7037e9 | |||
| 49c21a0a06 | |||
| d9d8a79c30 | |||
| 04840166af | |||
| 6fce6d4668 | |||
| 0c856b3d22 | |||
| d63cfc8eeb | |||
| 7621cc787d | |||
| 2c1682af34 | |||
| dcaa0987ee | |||
| 14a3bf3941 | |||
| 23b09015fe | |||
| b82e9c4d46 | |||
| c158874d82 | |||
| 87b7cd6368 | |||
| 901d7d07db | |||
| bfba988a0d | |||
| a7975c685d | |||
| cdaf4497b6 | |||
| 84807c5d61 | |||
| a76a6509e5 | |||
| 7d171e6722 | |||
| 36da551280 | |||
| ed665a12a3 | |||
| adec0265a4 | |||
| 8c700b19da | |||
| 9542313710 | |||
| dcb821edb5 | |||
| daa4adf2ed |
+41
-39
@@ -5,7 +5,7 @@ buildscript {
|
||||
dependencies {
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.7")
|
||||
classpath("org.asciidoctor:asciidoctor-gradle-plugin:0.7.0")
|
||||
classpath("io.spring.gradle:docbook-reference-plugin:0.3.0")
|
||||
classpath("io.spring.gradle:docbook-reference-plugin:0.3.1")
|
||||
classpath("ws.antonov.gradle.plugins:gradle-plugin-protobuf:0.9.1")
|
||||
}
|
||||
}
|
||||
@@ -27,34 +27,34 @@ configure(allprojects) { project ->
|
||||
group = "org.springframework"
|
||||
version = qualifyVersionIfNecessary(version)
|
||||
|
||||
ext.aspectjVersion = "1.8.4"
|
||||
ext.aspectjVersion = "1.8.6"
|
||||
ext.eclipseLinkVersion = "2.4.2"
|
||||
ext.ehcacheVersion = "2.9.0"
|
||||
ext.ehcacheJCacheVersion = "1.0.0"
|
||||
ext.groovyVersion = "2.3.9"
|
||||
ext.ehcacheVersion = "2.9.1"
|
||||
ext.ehcacheJCacheVersion = "1.0.1"
|
||||
ext.groovyVersion = "2.3.11"
|
||||
ext.gsonVersion = "2.3.1"
|
||||
ext.hibernate3Version = "3.6.10.Final"
|
||||
ext.hibernate4Version = "4.3.7.Final"
|
||||
ext.hibernate4Version = "4.3.10.Final"
|
||||
ext.hibVal4Version = "4.3.2.Final"
|
||||
ext.hibVal5Version = "5.1.3.Final"
|
||||
ext.hsqldbVersion = "2.3.2"
|
||||
ext.jackson2Version = "2.4.4"
|
||||
ext.jasperReportsVersion = "6.0.0"
|
||||
ext.jettyVersion = "9.2.6.v20141205"
|
||||
ext.jodaVersion = "2.6"
|
||||
ext.jackson2Version = "2.4.6"
|
||||
ext.jasperReportsVersion = "6.0.4"
|
||||
ext.jettyVersion = "9.2.11.v20150529"
|
||||
ext.jodaVersion = "2.8.1"
|
||||
ext.junitVersion = "4.12"
|
||||
ext.nettyVersion = "4.0.24.Final"
|
||||
ext.nettyVersion = "4.0.29.Final"
|
||||
ext.openJpaVersion = "2.2.2" // 2.3.0 not Java 8 compatible (based on ASM 4)
|
||||
ext.protobufVersion = "2.6.1"
|
||||
ext.reactorVersion = "1.1.5.RELEASE"
|
||||
ext.slf4jVersion = "1.7.9"
|
||||
ext.snakeYamlVersion = "1.14"
|
||||
ext.reactorVersion = "1.1.6.RELEASE"
|
||||
ext.slf4jVersion = "1.7.12"
|
||||
ext.snakeYamlVersion = "1.15"
|
||||
ext.snifferVersion = "1.11"
|
||||
ext.tiles2Version = "2.2.2"
|
||||
ext.tiles3Version = "3.0.5"
|
||||
ext.tomcatVersion = "8.0.15"
|
||||
ext.tomcatVersion = "8.0.23"
|
||||
ext.tyrusVersion = "1.3.5" // constrained by WebLogic 12.1.3 support
|
||||
ext.undertowVersion = "1.1.1.Final"
|
||||
ext.undertowVersion = "1.1.7.Final"
|
||||
ext.woodstoxVersion = "4.4.1"
|
||||
ext.xstreamVersion = "1.4.7"
|
||||
|
||||
@@ -86,13 +86,13 @@ configure(allprojects) { project ->
|
||||
"-Xlint:-unchecked", "-Xlint:-options"]
|
||||
|
||||
compileJava {
|
||||
sourceCompatibility=1.6
|
||||
targetCompatibility=1.6
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
}
|
||||
|
||||
compileTestJava {
|
||||
sourceCompatibility=1.8
|
||||
targetCompatibility=1.8
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
options.compilerArgs += "-parameters"
|
||||
}
|
||||
|
||||
@@ -143,7 +143,6 @@ configure(allprojects) { project ->
|
||||
|
||||
inputs.dir sourceSets.main.output.classesDir
|
||||
inputs.dir copyJavaApiSignature.to
|
||||
outputs.upToDateWhen { true }
|
||||
|
||||
doLast {
|
||||
ant.taskdef(
|
||||
@@ -334,7 +333,7 @@ project("spring-core") {
|
||||
optional("net.sf.jopt-simple:jopt-simple:4.8")
|
||||
optional("log4j:log4j:1.2.17")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
|
||||
testCompile("xmlunit:xmlunit:1.5")
|
||||
testCompile("xmlunit:xmlunit:1.6")
|
||||
testCompile("org.codehaus.woodstox:woodstox-core-asl:${woodstoxVersion}") {
|
||||
exclude group: "stax", module: "stax-api"
|
||||
}
|
||||
@@ -389,8 +388,8 @@ project("spring-beans-groovy") {
|
||||
}
|
||||
|
||||
compileGroovy {
|
||||
sourceCompatibility=1.6
|
||||
targetCompatibility=1.6
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,7 +404,7 @@ project("spring-aop") {
|
||||
compile("aopalliance:aopalliance:1.0")
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("commons-pool:commons-pool:1.6")
|
||||
optional("com.jamonapi:jamon:2.79")
|
||||
optional("com.jamonapi:jamon:2.81")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,7 +459,7 @@ project("spring-context") {
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||
optional("org.beanshell:bsh:2.0b4")
|
||||
optional("org.jruby:jruby:1.7.17")
|
||||
optional("org.jruby:jruby:1.7.19")
|
||||
testCompile("javax.inject:javax.inject-tck:1")
|
||||
testCompile("commons-dbcp:commons-dbcp:1.4")
|
||||
testCompile("org.slf4j:slf4j-api:${slf4jVersion}")
|
||||
@@ -534,8 +533,8 @@ project("spring-oxm") {
|
||||
compileTestJava {
|
||||
// necessary to avoid java.lang.VerifyError on jibx compilation
|
||||
// see http://jira.codehaus.org/browse/JIBX-465
|
||||
sourceCompatibility=1.6
|
||||
targetCompatibility=1.6
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -552,9 +551,9 @@ project("spring-oxm") {
|
||||
exclude group: 'xpp3', module: 'xpp3_min'
|
||||
exclude group: 'xmlpull', module: 'xmlpull'
|
||||
}
|
||||
optional("org.jibx:jibx-run:1.2.5")
|
||||
optional("org.jibx:jibx-run:1.2.6")
|
||||
testCompile(project(":spring-context"))
|
||||
testCompile("xmlunit:xmlunit:1.5")
|
||||
testCompile("xmlunit:xmlunit:1.6")
|
||||
testCompile("xpp3:xpp3:1.1.4c")
|
||||
testCompile("org.codehaus.jettison:jettison:1.3.7") {
|
||||
exclude group: 'stax', module: 'stax-api'
|
||||
@@ -595,7 +594,7 @@ project("spring-jdbc") {
|
||||
optional("javax.transaction:javax.transaction-api:1.2")
|
||||
optional("com.mchange:c3p0:0.9.2.1")
|
||||
optional("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
optional("com.h2database:h2:1.4.182")
|
||||
optional("com.h2database:h2:1.4.187")
|
||||
optional("org.apache.derby:derby:10.11.1.1")
|
||||
optional("org.apache.derby:derbyclient:10.11.1.1")
|
||||
}
|
||||
@@ -617,7 +616,7 @@ project("spring-context-support") {
|
||||
optional("org.quartz-scheduler:quartz:2.2.1")
|
||||
optional("org.codehaus.fabric3.api:commonj:1.1.0")
|
||||
optional("org.apache.velocity:velocity:1.7")
|
||||
optional("org.freemarker:freemarker:2.3.21")
|
||||
optional("org.freemarker:freemarker:2.3.22")
|
||||
optional("com.lowagie:itext:2.1.7")
|
||||
optional("net.sf.jasperreports:jasperreports:$jasperReportsVersion") {
|
||||
exclude group: "com.fasterxml.jackson.core", module: "jackson-annotations"
|
||||
@@ -625,9 +624,10 @@ project("spring-context-support") {
|
||||
exclude group: "com.fasterxml.jackson.core", module: "jackson-databind"
|
||||
exclude group: "org.olap4j", module: "olap4j"
|
||||
exclude group: "xml-apis", module: "xml-apis"
|
||||
exclude group: "org.springframework", module: "spring-context"
|
||||
}
|
||||
testCompile(project(":spring-context"))
|
||||
testCompile("org.apache.poi:poi:3.10.1")
|
||||
testCompile("org.apache.poi:poi:3.11")
|
||||
testCompile("commons-beanutils:commons-beanutils:1.8.0") // for Velocity/JasperReports
|
||||
testCompile("commons-digester:commons-digester:1.8.1") // for Velocity/JasperReports
|
||||
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
@@ -692,11 +692,12 @@ project("spring-web") {
|
||||
optional("com.google.protobuf:protobuf-java:${protobufVersion}")
|
||||
optional("javax.mail:javax.mail-api:1.5.2")
|
||||
testCompile(project(":spring-context-support")) // for JafMediaTypeFactory
|
||||
testCompile("xmlunit:xmlunit:1.5")
|
||||
testCompile("xmlunit:xmlunit:1.6")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
testCompile("org.apache.taglibs:taglibs-standard-jstlel:1.2.1") {
|
||||
exclude group: "org.apache.taglibs", module: "taglibs-standard-spec"
|
||||
}
|
||||
testCompile("com.fasterxml.jackson.datatype:jackson-datatype-joda:${jackson2Version}")
|
||||
testRuntime("com.sun.mail:javax.mail:1.5.2")
|
||||
}
|
||||
|
||||
@@ -826,10 +827,10 @@ project("spring-webmvc") {
|
||||
optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
|
||||
optional("javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1")
|
||||
optional("net.sourceforge.jexcelapi:jxl:2.6.12")
|
||||
optional("org.apache.poi:poi:3.10.1")
|
||||
optional("org.apache.poi:poi:3.11")
|
||||
optional("org.apache.velocity:velocity:1.7")
|
||||
optional("velocity-tools:velocity-tools-view:1.4")
|
||||
optional("org.freemarker:freemarker:2.3.20")
|
||||
optional("org.freemarker:freemarker:2.3.22")
|
||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||
optional("com.lowagie:itext:2.1.7")
|
||||
optional("net.sf.jasperreports:jasperreports:$jasperReportsVersion") {
|
||||
@@ -838,6 +839,7 @@ project("spring-webmvc") {
|
||||
exclude group: "com.fasterxml.jackson.core", module: "jackson-databind"
|
||||
exclude group: "org.olap4j", module: "olap4j"
|
||||
exclude group: "xml-apis", module: "xml-apis"
|
||||
exclude group: "org.springframework", module: "spring-context"
|
||||
}
|
||||
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
|
||||
optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:${jackson2Version}")
|
||||
@@ -862,7 +864,7 @@ project("spring-webmvc") {
|
||||
}
|
||||
testCompile(project(":spring-aop"))
|
||||
testCompile("rhino:js:1.7R1")
|
||||
testCompile("xmlunit:xmlunit:1.5")
|
||||
testCompile("xmlunit:xmlunit:1.6")
|
||||
testCompile("dom4j:dom4j:1.6.1") {
|
||||
exclude group: "xml-apis", module: "xml-apis"
|
||||
}
|
||||
@@ -967,9 +969,9 @@ project("spring-test") {
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||
optional("org.hamcrest:hamcrest-core:1.3")
|
||||
optional("com.jayway.jsonpath:json-path:1.1.0")
|
||||
optional("com.jayway.jsonpath:json-path:1.2.0")
|
||||
optional("org.skyscreamer:jsonassert:1.2.3")
|
||||
optional("xmlunit:xmlunit:1.5")
|
||||
optional("xmlunit:xmlunit:1.6")
|
||||
testCompile(project(":spring-context-support"))
|
||||
testCompile(project(":spring-oxm"))
|
||||
testCompile("javax.mail:javax.mail-api:1.5.2")
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=4.1.4.BUILD-SNAPSHOT
|
||||
version=4.1.7.RELEASE
|
||||
|
||||
+36
-24
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.aop.aspectj;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -203,8 +204,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
pointcutParameters[i] = parser.createPointcutParameter(
|
||||
this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
|
||||
}
|
||||
return parser.parsePointcutExpression(
|
||||
replaceBooleanOperators(getExpression()),
|
||||
return parser.parsePointcutExpression(replaceBooleanOperators(getExpression()),
|
||||
this.pointcutDeclarationScope, pointcutParameters);
|
||||
}
|
||||
|
||||
@@ -327,29 +327,41 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
catch (IllegalStateException ex) {
|
||||
// No current invocation...
|
||||
// TODO: Should we really proceed here?
|
||||
logger.debug("Couldn't access current invocation - matching with limited context: " + ex);
|
||||
}
|
||||
|
||||
JoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args);
|
||||
|
||||
/*
|
||||
* Do a final check to see if any this(TYPE) kind of residue match. For
|
||||
* this purpose, we use the original method's (proxy method's) shadow to
|
||||
* ensure that 'this' is correctly checked against. Without this check,
|
||||
* we get incorrect match on this(TYPE) where TYPE matches the target
|
||||
* type but not 'this' (as would be the case of JDK dynamic proxies).
|
||||
* <p>See SPR-2979 for the original bug.
|
||||
*/
|
||||
if (pmi != null) { // there is a current invocation
|
||||
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(originalShadowMatch);
|
||||
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
|
||||
return false;
|
||||
}
|
||||
if (joinPointMatch.matches()) {
|
||||
bindParameters(pmi, joinPointMatch);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not access current invocation - matching with limited context: " + ex);
|
||||
}
|
||||
}
|
||||
return joinPointMatch.matches();
|
||||
|
||||
try {
|
||||
JoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args);
|
||||
|
||||
/*
|
||||
* Do a final check to see if any this(TYPE) kind of residue match. For
|
||||
* this purpose, we use the original method's (proxy method's) shadow to
|
||||
* ensure that 'this' is correctly checked against. Without this check,
|
||||
* we get incorrect match on this(TYPE) where TYPE matches the target
|
||||
* type but not 'this' (as would be the case of JDK dynamic proxies).
|
||||
* <p>See SPR-2979 for the original bug.
|
||||
*/
|
||||
if (pmi != null) { // there is a current invocation
|
||||
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(originalShadowMatch);
|
||||
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
|
||||
return false;
|
||||
}
|
||||
if (joinPointMatch.matches()) {
|
||||
bindParameters(pmi, joinPointMatch);
|
||||
}
|
||||
}
|
||||
|
||||
return joinPointMatch.matches();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to evaluate join point for arguments " + Arrays.asList(args) +
|
||||
" - falling back to non-match", ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected String getCurrentProxiedBeanName() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -102,9 +102,9 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
/** The configuration used to configure this proxy */
|
||||
protected final AdvisedSupport advised;
|
||||
|
||||
private Object[] constructorArgs;
|
||||
protected Object[] constructorArgs;
|
||||
|
||||
private Class<?>[] constructorArgTypes;
|
||||
protected Class<?>[] constructorArgTypes;
|
||||
|
||||
/** Dispatcher used for methods on Advised */
|
||||
private final transient AdvisedDispatcher advisedDispatcher;
|
||||
|
||||
+28
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,14 +22,14 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cglib.proxy.Callback;
|
||||
import org.springframework.cglib.proxy.Enhancer;
|
||||
import org.springframework.cglib.proxy.Factory;
|
||||
import org.springframework.objenesis.ObjenesisException;
|
||||
import org.springframework.objenesis.ObjenesisStd;
|
||||
|
||||
/**
|
||||
* Objenesis based extension of {@link CglibAopProxy} to create proxy instances without
|
||||
* invoking the constructor of the class.
|
||||
* Objenesis-based extension of {@link CglibAopProxy} to create proxy instances
|
||||
* without invoking the constructor of the class.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@@ -41,8 +41,8 @@ class ObjenesisCglibAopProxy extends CglibAopProxy {
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link ObjenesisCglibAopProxy} using the given {@link AdvisedSupport}.
|
||||
* @param config must not be {@literal null}.
|
||||
* Create a new ObjenesisCglibAopProxy for the given AOP configuration.
|
||||
* @param config the AOP configuration as AdvisedSupport object
|
||||
*/
|
||||
public ObjenesisCglibAopProxy(AdvisedSupport config) {
|
||||
super(config);
|
||||
@@ -53,18 +53,32 @@ class ObjenesisCglibAopProxy extends CglibAopProxy {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
|
||||
Class<?> proxyClass = enhancer.createClass();
|
||||
Object proxyInstance = null;
|
||||
|
||||
try {
|
||||
Factory factory = (Factory) this.objenesis.newInstance(enhancer.createClass());
|
||||
factory.setCallbacks(callbacks);
|
||||
return factory;
|
||||
proxyInstance = this.objenesis.newInstance(proxyClass);
|
||||
}
|
||||
catch (ObjenesisException ex) {
|
||||
// Fallback to regular proxy construction on unsupported JVMs
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Unable to instantiate proxy using Objenesis, falling back to regular proxy construction", ex);
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Unable to instantiate proxy using Objenesis, " +
|
||||
"falling back to regular proxy construction", ex);
|
||||
}
|
||||
|
||||
if (proxyInstance == null) {
|
||||
// Regular instantiation via default constructor...
|
||||
try {
|
||||
proxyInstance = (this.constructorArgs != null ?
|
||||
proxyClass.getConstructor(this.constructorArgTypes).newInstance(this.constructorArgs) :
|
||||
proxyClass.newInstance());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
|
||||
"and regular proxy instantiation via default constructor fails as well", ex);
|
||||
}
|
||||
return super.createProxyClassAndInstance(enhancer, callbacks);
|
||||
}
|
||||
|
||||
((Factory) proxyInstance).setCallbacks(callbacks);
|
||||
return proxyInstance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -155,7 +155,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
/**
|
||||
* Handles a fatal error thrown while asynchronously invoking the specified
|
||||
* {@link Method}.
|
||||
* <p>If the return type of the method is a {@link java.util.concurrent.Future} object, the original
|
||||
* <p>If the return type of the method is a {@link Future} object, the original
|
||||
* exception can be propagated by just throwing it at the higher level. However,
|
||||
* for all other cases, the exception will not be transmitted back to the client.
|
||||
* In that later case, the current {@link AsyncUncaughtExceptionHandler} will be
|
||||
@@ -165,7 +165,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
* @param params the parameters used to invoke the method
|
||||
*/
|
||||
protected void handleError(Throwable ex, Method method, Object... params) throws Exception {
|
||||
if (method.getReturnType().isAssignableFrom(Future.class)) {
|
||||
if (Future.class.isAssignableFrom(method.getReturnType())) {
|
||||
ReflectionUtils.rethrowException(ex);
|
||||
}
|
||||
else {
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ public class CommonsPoolTargetSource extends AbstractPoolingTargetSource impleme
|
||||
private byte whenExhaustedAction = GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
|
||||
|
||||
/**
|
||||
* The Jakarta Commons {@code ObjectPool} used to pool target objects
|
||||
* The Apache Commons {@code ObjectPool} used to pool target objects
|
||||
*/
|
||||
private ObjectPool pool;
|
||||
|
||||
|
||||
+38
-33
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,50 +32,55 @@ import static org.mockito.BDDMockito.*;
|
||||
*/
|
||||
public class JamonPerformanceMonitorInterceptorTests {
|
||||
|
||||
private JamonPerformanceMonitorInterceptor interceptor = new JamonPerformanceMonitorInterceptor();
|
||||
private final JamonPerformanceMonitorInterceptor interceptor = new JamonPerformanceMonitorInterceptor();
|
||||
|
||||
private MethodInvocation mi = mock(MethodInvocation.class);
|
||||
private final MethodInvocation mi = mock(MethodInvocation.class);
|
||||
|
||||
private Log log = mock(Log.class);
|
||||
private final Log log = mock(Log.class);
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MonitorFactory.reset();
|
||||
}
|
||||
@Before
|
||||
public void setUp() {
|
||||
MonitorFactory.reset();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
MonitorFactory.reset();
|
||||
}
|
||||
@After
|
||||
public void tearDown() {
|
||||
MonitorFactory.reset();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testInvokeUnderTraceWithNormalProcessing() throws Throwable {
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
@Test
|
||||
public void testInvokeUnderTraceWithNormalProcessing() throws Throwable {
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
|
||||
assertEquals("jamon must track the method being invoked", 1, MonitorFactory.getNumRows());
|
||||
assertTrue("The jamon report must contain the toString method that was invoked", MonitorFactory.getReport().contains("toString"));
|
||||
}
|
||||
assertTrue("jamon must track the method being invoked", MonitorFactory.getNumRows() > 0);
|
||||
assertTrue("The jamon report must contain the toString method that was invoked",
|
||||
MonitorFactory.getReport().contains("toString"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvokeUnderTraceWithExceptionTracking() throws Throwable {
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(mi.proceed()).willThrow(new IllegalArgumentException());
|
||||
@Test
|
||||
public void testInvokeUnderTraceWithExceptionTracking() throws Throwable {
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(mi.proceed()).willThrow(new IllegalArgumentException());
|
||||
|
||||
try {
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
fail("Must have propagated the IllegalArgumentException");
|
||||
}
|
||||
try {
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
fail("Must have propagated the IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals("Monitors must exist for the method invocation and 2 exceptions", 3, MonitorFactory.getNumRows());
|
||||
assertTrue("The jamon report must contain the toString method that was invoked", MonitorFactory.getReport().contains("toString"));
|
||||
assertTrue("The jamon report must contain the generic exception: " + MonitorFactory.EXCEPTIONS_LABEL, MonitorFactory.getReport().contains(MonitorFactory.EXCEPTIONS_LABEL));
|
||||
assertTrue("The jamon report must contain the specific exception: IllegalArgumentException'", MonitorFactory.getReport().contains("IllegalArgumentException"));
|
||||
}
|
||||
assertEquals("Monitors must exist for the method invocation and 2 exceptions",
|
||||
3, MonitorFactory.getNumRows());
|
||||
assertTrue("The jamon report must contain the toString method that was invoked",
|
||||
MonitorFactory.getReport().contains("toString"));
|
||||
assertTrue("The jamon report must contain the generic exception: " + MonitorFactory.EXCEPTIONS_LABEL,
|
||||
MonitorFactory.getReport().contains(MonitorFactory.EXCEPTIONS_LABEL));
|
||||
assertTrue("The jamon report must contain the specific exception: IllegalArgumentException'",
|
||||
MonitorFactory.getReport().contains("IllegalArgumentException"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,9 +28,9 @@ import org.springframework.context.annotation.Role;
|
||||
* annotated with @{@link org.springframework.beans.factory.annotation.Configurable
|
||||
* Configurable}.
|
||||
*
|
||||
* <p>This configuration class is automatically imported when using the @{@link
|
||||
* EnableSpringConfigured} annotation. See {@code @EnableSpringConfigured} Javadoc for
|
||||
* complete usage details.
|
||||
* <p>This configuration class is automatically imported when using the
|
||||
* @{@link EnableSpringConfigured} annotation. See {@code @EnableSpringConfigured}'s
|
||||
* javadoc for complete usage details.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
@@ -42,9 +42,10 @@ public class SpringConfiguredConfiguration {
|
||||
public static final String BEAN_CONFIGURER_ASPECT_BEAN_NAME =
|
||||
"org.springframework.context.config.internalBeanConfigurerAspect";
|
||||
|
||||
@Bean(name=BEAN_CONFIGURER_ASPECT_BEAN_NAME)
|
||||
@Bean(name = BEAN_CONFIGURER_ASPECT_BEAN_NAME)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public AnnotationBeanConfigurerAspect beanConfigurerAspect() {
|
||||
return AnnotationBeanConfigurerAspect.aspectOf();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+23
-24
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,15 +23,15 @@ import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
/**
|
||||
* Aspect to route methods based on the {@link Async} annotation.
|
||||
* Aspect to route methods based on Spring's {@link Async} annotation.
|
||||
*
|
||||
* <p>This aspect routes methods marked with the {@link Async} annotation
|
||||
* as well as methods in classes marked with the same. Any method expected
|
||||
* to be routed asynchronously must return either {@code void}, {@link Future},
|
||||
* or a subtype of {@link Future}. This aspect, therefore, will produce
|
||||
* a compile-time error for methods that violate this constraint on the return type.
|
||||
* If, however, a class marked with {@code @Async} contains a method that violates this
|
||||
* constraint, it produces only a warning.
|
||||
* <p>This aspect routes methods marked with the {@link Async} annotation as well as methods
|
||||
* in classes marked with the same. Any method expected to be routed asynchronously must
|
||||
* return either {@code void}, {@link Future}, or a subtype of {@link Future} (in particular,
|
||||
* Spring's {@link org.springframework.util.concurrent.ListenableFuture}). This aspect,
|
||||
* therefore, will produce a compile-time error for methods that violate this constraint
|
||||
* on the return type. If, however, a class marked with {@code @Async} contains a method
|
||||
* that violates this constraint, it produces only a warning.
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
* @author Chris Beams
|
||||
@@ -39,42 +39,41 @@ import org.springframework.scheduling.annotation.Async;
|
||||
*/
|
||||
public aspect AnnotationAsyncExecutionAspect extends AbstractAsyncExecutionAspect {
|
||||
|
||||
private pointcut asyncMarkedMethod()
|
||||
: execution(@Async (void || Future+) *(..));
|
||||
private pointcut asyncMarkedMethod() : execution(@Async (void || Future+) *(..));
|
||||
|
||||
private pointcut asyncTypeMarkedMethod()
|
||||
: execution((void || Future+) (@Async *).*(..));
|
||||
private pointcut asyncTypeMarkedMethod() : execution((void || Future+) (@Async *).*(..));
|
||||
|
||||
public pointcut asyncMethod() : asyncMarkedMethod() || asyncTypeMarkedMethod();
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>This implementation inspects the given method and its declaring class for the
|
||||
* {@code @Async} annotation, returning the qualifier value expressed by
|
||||
* {@link Async#value()}. If {@code @Async} is specified at both the method and class level, the
|
||||
* method's {@code #value} takes precedence (even if empty string, indicating that
|
||||
* the default executor should be used preferentially).
|
||||
* This implementation inspects the given method and its declaring class for the
|
||||
* {@code @Async} annotation, returning the qualifier value expressed by {@link Async#value()}.
|
||||
* If {@code @Async} is specified at both the method and class level, the method's
|
||||
* {@code #value} takes precedence (even if empty string, indicating that the default
|
||||
* executor should be used preferentially).
|
||||
* @return the qualifier if specified, otherwise empty string indicating that the
|
||||
* {@linkplain #setExecutor(Executor) default executor} should be used
|
||||
* {@linkplain #setExecutor default executor} should be used
|
||||
* @see #determineAsyncExecutor(Method)
|
||||
*/
|
||||
@Override
|
||||
protected String getExecutorQualifier(Method method) {
|
||||
// maintainer's note: changes made here should also be made in
|
||||
// Maintainer's note: changes made here should also be made in
|
||||
// AnnotationAsyncExecutionInterceptor#getExecutorQualifier
|
||||
Async async = AnnotationUtils.findAnnotation(method, Async.class);
|
||||
if (async == null) {
|
||||
async = AnnotationUtils.findAnnotation(method.getDeclaringClass(), Async.class);
|
||||
}
|
||||
return async == null ? null : async.value();
|
||||
return (async != null ? async.value() : null);
|
||||
}
|
||||
|
||||
|
||||
declare error:
|
||||
execution(@Async !(void||Future) *(..)):
|
||||
execution(@Async !(void || Future+) *(..)):
|
||||
"Only methods that return void or Future may have an @Async annotation";
|
||||
|
||||
declare warning:
|
||||
execution(!(void||Future) (@Async *).*(..)):
|
||||
execution(!(void || Future+) (@Async *).*(..)):
|
||||
"Methods in a class marked with @Async that do not return void or Future will " +
|
||||
"be routed synchronously";
|
||||
|
||||
|
||||
+13
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,6 +35,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.tests.Assume;
|
||||
import org.springframework.tests.TestGroup;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
@@ -50,9 +51,10 @@ public class AnnotationAsyncExecutionAspectTests {
|
||||
|
||||
private static final long WAIT_TIME = 1000; //milliseconds
|
||||
|
||||
private final AsyncUncaughtExceptionHandler defaultExceptionHandler = new SimpleAsyncUncaughtExceptionHandler();
|
||||
|
||||
private CountingExecutor executor;
|
||||
|
||||
private AsyncUncaughtExceptionHandler defaultExceptionHandler = new SimpleAsyncUncaughtExceptionHandler();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -62,6 +64,7 @@ public class AnnotationAsyncExecutionAspectTests {
|
||||
AnnotationAsyncExecutionAspect.aspectOf().setExecutor(executor);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void asyncMethodGetsRoutedAsynchronously() {
|
||||
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
|
||||
@@ -184,7 +187,9 @@ public class AnnotationAsyncExecutionAspectTests {
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class CountingExecutor extends SimpleAsyncTaskExecutor {
|
||||
|
||||
int submitStartCounter;
|
||||
|
||||
int submitCompleteCounter;
|
||||
|
||||
@Override
|
||||
@@ -209,6 +214,7 @@ public class AnnotationAsyncExecutionAspectTests {
|
||||
|
||||
|
||||
static class ClassWithoutAsyncAnnotation {
|
||||
|
||||
int counter;
|
||||
|
||||
@Async public void incrementAsync() {
|
||||
@@ -239,6 +245,7 @@ public class AnnotationAsyncExecutionAspectTests {
|
||||
|
||||
@Async
|
||||
static class ClassWithAsyncAnnotation {
|
||||
|
||||
int counter;
|
||||
|
||||
public void increment() {
|
||||
@@ -261,17 +268,19 @@ public class AnnotationAsyncExecutionAspectTests {
|
||||
|
||||
|
||||
static class ClassWithQualifiedAsyncMethods {
|
||||
|
||||
@Async
|
||||
public Future<Thread> defaultWork() {
|
||||
return new AsyncResult<Thread>(Thread.currentThread());
|
||||
}
|
||||
|
||||
@Async("e1")
|
||||
public Future<Thread> e1Work() {
|
||||
public ListenableFuture<Thread> e1Work() {
|
||||
return new AsyncResult<Thread>(Thread.currentThread());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class ClassWithException {
|
||||
|
||||
@Async
|
||||
@@ -279,4 +288,5 @@ public class AnnotationAsyncExecutionAspectTests {
|
||||
throw new UnsupportedOperationException("failWithVoid");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+64
-47
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,6 +31,7 @@ import groovy.lang.GroovyObjectSupport;
|
||||
import groovy.lang.GroovyShell;
|
||||
import groovy.lang.GroovySystem;
|
||||
import groovy.lang.MetaClass;
|
||||
|
||||
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
|
||||
import org.codehaus.groovy.runtime.InvokerHelper;
|
||||
|
||||
@@ -58,8 +59,17 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A Groovy-based reader for Spring bean definitions: like a Groovy builder,
|
||||
* but more of a DSL for Spring configuration. Allows syntax like:
|
||||
* but more of a DSL for Spring configuration.
|
||||
*
|
||||
* <p>This bean definition reader also understands XML bean definition files,
|
||||
* allowing for seamless mixing and matching with Groovy bean definition files.
|
||||
*
|
||||
* <p>Typically applied to a
|
||||
* {@link org.springframework.beans.factory.support.DefaultListableBeanFactory}
|
||||
* or a {@link org.springframework.context.support.GenericApplicationContext},
|
||||
* but can be used against any {@link BeanDefinitionRegistry} implementation.
|
||||
*
|
||||
* <h3>Example Syntax</h3>
|
||||
* <pre class="code">
|
||||
* import org.hibernate.SessionFactory
|
||||
* import org.apache.commons.dbcp.BasicDataSource
|
||||
@@ -84,8 +94,9 @@ import org.springframework.util.StringUtils;
|
||||
* }</pre>
|
||||
*
|
||||
* <p>You can also load resources containing beans defined in a Groovy script using
|
||||
* either the {@link #loadBeanDefinitions(org.springframework.core.io.Resource...)}
|
||||
* or {@link #loadBeanDefinitions(String...)} method, with a script looking as follows:
|
||||
* either the {@link #loadBeanDefinitions(Resource...)} or
|
||||
* {@link #loadBeanDefinitions(String...)} method, with a script looking similar to
|
||||
* the following.
|
||||
*
|
||||
* <pre class="code">
|
||||
* import org.hibernate.SessionFactory
|
||||
@@ -109,17 +120,10 @@ import org.springframework.util.StringUtils;
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* <p><b>This bean definition reader also understands XML bean definition files,
|
||||
* allowing for seamless mixing and matching with Groovy bean definition files.</b>
|
||||
*
|
||||
* <p>Typically applied to a
|
||||
* {@link org.springframework.beans.factory.support.DefaultListableBeanFactory}
|
||||
* or a {@link org.springframework.context.support.GenericApplicationContext},
|
||||
* but can be used against any {@link BeanDefinitionRegistry} implementation.
|
||||
*
|
||||
* @author Jeff Brown
|
||||
* @author Graeme Rocher
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 4.0
|
||||
* @see BeanDefinitionRegistry
|
||||
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory
|
||||
@@ -128,7 +132,21 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader implements GroovyObject {
|
||||
|
||||
private final XmlBeanDefinitionReader xmlBeanDefinitionReader;
|
||||
/**
|
||||
* Standard {@code XmlBeanDefinitionReader} created with default
|
||||
* settings for loading bean definitions from XML files.
|
||||
*/
|
||||
private final XmlBeanDefinitionReader standardXmlBeanDefinitionReader;
|
||||
|
||||
/**
|
||||
* Groovy DSL {@code XmlBeanDefinitionReader} for loading bean definitions
|
||||
* via the Groovy DSL, typically configured with XML validation disabled.
|
||||
*/
|
||||
private final XmlBeanDefinitionReader groovyDslXmlBeanDefinitionReader;
|
||||
|
||||
private final Map<String, String> namespaces = new HashMap<String, String>();
|
||||
|
||||
private final Map<String, DeferredProperty> deferredProperties = new HashMap<String, DeferredProperty>();
|
||||
|
||||
private MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(getClass());
|
||||
|
||||
@@ -136,31 +154,28 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
|
||||
private GroovyBeanDefinitionWrapper currentBeanDefinition;
|
||||
|
||||
private final Map <String, String> namespaces = new HashMap<String, String>();
|
||||
|
||||
private final Map<String, DeferredProperty> deferredProperties = new HashMap<String, DeferredProperty>();
|
||||
|
||||
|
||||
/**
|
||||
* Create new GroovyBeanDefinitionReader for the given bean factory.
|
||||
* @param registry the BeanFactory to load bean definitions into,
|
||||
* in the form of a BeanDefinitionRegistry
|
||||
* Create a new {@code GroovyBeanDefinitionReader} for the given {@link BeanDefinitionRegistry}.
|
||||
* @param registry the {@code BeanDefinitionRegistry} to load bean definitions into
|
||||
*/
|
||||
public GroovyBeanDefinitionReader(BeanDefinitionRegistry registry) {
|
||||
super(registry);
|
||||
this.xmlBeanDefinitionReader = new XmlBeanDefinitionReader(registry);
|
||||
this.xmlBeanDefinitionReader.setValidating(false);
|
||||
this.standardXmlBeanDefinitionReader = new XmlBeanDefinitionReader(registry);
|
||||
this.groovyDslXmlBeanDefinitionReader = new XmlBeanDefinitionReader(registry);
|
||||
this.groovyDslXmlBeanDefinitionReader.setValidating(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new GroovyBeanDefinitionReader based on the given XmlBeanDefinitionReader,
|
||||
* using the same registry and delegating XML loading to it.
|
||||
* @param xmlBeanDefinitionReader the XmlBeanDefinitionReader to derive the registry
|
||||
* Create a new {@code GroovyBeanDefinitionReader} based on the given {@link XmlBeanDefinitionReader},
|
||||
* using its {@code BeanDefinitionRegistry} and delegating Groovy DSL loading to it.
|
||||
* @param xmlBeanDefinitionReader the {@code XmlBeanDefinitionReader} to derive the registry
|
||||
* from and to delegate XML loading to
|
||||
*/
|
||||
public GroovyBeanDefinitionReader(XmlBeanDefinitionReader xmlBeanDefinitionReader) {
|
||||
super(xmlBeanDefinitionReader.getRegistry());
|
||||
this.xmlBeanDefinitionReader = xmlBeanDefinitionReader;
|
||||
this.standardXmlBeanDefinitionReader = new XmlBeanDefinitionReader(xmlBeanDefinitionReader.getRegistry());
|
||||
this.groovyDslXmlBeanDefinitionReader = xmlBeanDefinitionReader;
|
||||
}
|
||||
|
||||
|
||||
@@ -174,7 +189,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
|
||||
/**
|
||||
* Set the binding, i.e. the Groovy variables available in the scope
|
||||
* of a GroovyBeanDefinitionReader closure.
|
||||
* of a {@code GroovyBeanDefinitionReader} closure.
|
||||
*/
|
||||
public void setBinding(Binding binding) {
|
||||
this.binding = binding;
|
||||
@@ -192,9 +207,9 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
|
||||
/**
|
||||
* Load bean definitions from the specified Groovy script or XML file.
|
||||
* <p>Note that ".xml" files will be parsed as XML content; all other kinds
|
||||
* <p>Note that {@code ".xml"} files will be parsed as XML content; all other kinds
|
||||
* of resources will be parsed as Groovy scripts.
|
||||
* @param resource the resource descriptor for the Groovy script
|
||||
* @param resource the resource descriptor for the Groovy script or XML file
|
||||
* @return the number of bean definitions found
|
||||
* @throws BeanDefinitionStoreException in case of loading or parsing errors
|
||||
*/
|
||||
@@ -204,18 +219,18 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
|
||||
/**
|
||||
* Load bean definitions from the specified Groovy script or XML file.
|
||||
* <p>Note that ".xml" files will be parsed as XML content; all other kinds
|
||||
* <p>Note that {@code ".xml"} files will be parsed as XML content; all other kinds
|
||||
* of resources will be parsed as Groovy scripts.
|
||||
* @param encodedResource the resource descriptor for the Groovy script,
|
||||
* allowing to specify an encoding to use for parsing the file
|
||||
* @param encodedResource the resource descriptor for the Groovy script or XML file,
|
||||
* allowing specification of an encoding to use for parsing the file
|
||||
* @return the number of bean definitions found
|
||||
* @throws BeanDefinitionStoreException in case of loading or parsing errors
|
||||
*/
|
||||
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
|
||||
// Check for XML files and redirect them to the XmlBeanDefinitionReader
|
||||
// Check for XML files and redirect them to the "standard" XmlBeanDefinitionReader
|
||||
String filename = encodedResource.getResource().getFilename();
|
||||
if (StringUtils.endsWithIgnoreCase(filename, ".xml")) {
|
||||
return this.xmlBeanDefinitionReader.loadBeanDefinitions(encodedResource);
|
||||
return this.standardXmlBeanDefinitionReader.loadBeanDefinitions(encodedResource);
|
||||
}
|
||||
|
||||
Closure beans = new Closure(this) {
|
||||
@@ -255,14 +270,14 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
/**
|
||||
* Defines a set of beans for the given block or closure.
|
||||
* @param closure the block or closure
|
||||
* @return this GroovyBeanDefinitionReader instance
|
||||
* @return this {@code GroovyBeanDefinitionReader} instance
|
||||
*/
|
||||
public GroovyBeanDefinitionReader beans(Closure closure) {
|
||||
return invokeBeanDefiningClosure(closure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines an inner bean definition.
|
||||
* Define an inner bean definition.
|
||||
* @param type the bean type
|
||||
* @return the bean definition
|
||||
*/
|
||||
@@ -307,7 +322,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a Spring namespace definition to use.
|
||||
* Define a Spring XML namespace definition to use.
|
||||
* @param definition the namespace definition
|
||||
*/
|
||||
public void xmlns(Map<String, String> definition) {
|
||||
@@ -318,7 +333,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
if (uri == null) {
|
||||
throw new IllegalArgumentException("Namespace definition must supply a non-null URI");
|
||||
}
|
||||
NamespaceHandler namespaceHandler = this.xmlBeanDefinitionReader.getNamespaceHandlerResolver().resolve(uri);
|
||||
NamespaceHandler namespaceHandler = this.groovyDslXmlBeanDefinitionReader.getNamespaceHandlerResolver().resolve(
|
||||
uri);
|
||||
if (namespaceHandler == null) {
|
||||
throw new BeanDefinitionParsingException(new Problem("No namespace handler found for URI: " + uri,
|
||||
new Location(new DescriptiveResource(("Groovy")))));
|
||||
@@ -419,7 +435,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
/**
|
||||
* When a method argument is only a closure it is a set of bean definitions.
|
||||
* @param callable the closure argument
|
||||
* @return this GroovyBeanDefinitionReader instance
|
||||
* @return this {@code GroovyBeanDefinitionReader} instance
|
||||
*/
|
||||
protected GroovyBeanDefinitionReader invokeBeanDefiningClosure(Closure callable) {
|
||||
callable.setDelegate(this);
|
||||
@@ -534,8 +550,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether there are any {@link RuntimeBeanReference}s inside the Map
|
||||
* and converts it to a ManagedMap if necessary.
|
||||
* Checks whether there are any {@link RuntimeBeanReference}s inside the {@link Map}
|
||||
* and converts it to a {@link ManagedMap} if necessary.
|
||||
* @param map the original Map
|
||||
* @return either the original map or a managed copy of it
|
||||
*/
|
||||
@@ -556,8 +572,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether there are any {@link RuntimeBeanReference}s inside the List
|
||||
* and converts it to a ManagedList if necessary.
|
||||
* Checks whether there are any {@link RuntimeBeanReference}s inside the {@link List}
|
||||
* and converts it to a {@link ManagedList} if necessary.
|
||||
* @param list the original List
|
||||
* @return either the original list or a managed copy of it
|
||||
*/
|
||||
@@ -578,7 +594,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
|
||||
/**
|
||||
* This method overrides property setting in the scope of the GroovyBeanDefinitionReader
|
||||
* This method overrides property setting in the scope of the {@code GroovyBeanDefinitionReader}
|
||||
* to set properties on the current bean definition.
|
||||
*/
|
||||
public void setProperty(String name, Object value) {
|
||||
@@ -619,12 +635,12 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
|
||||
/**
|
||||
* This method overrides property retrieval in the scope of the
|
||||
* GroovyBeanDefinitionReader to either:
|
||||
* {@code GroovyBeanDefinitionReader} to either:
|
||||
* <ul>
|
||||
* <li>Retrieve a variable from the bean builder's binding if it exists
|
||||
* <li>Retrieve a RuntimeBeanReference for a specific bean if it exists
|
||||
* <li>Otherwise just delegate to MetaClass.getProperty which will resolve
|
||||
* properties from the GroovyBeanDefinitionReader itself
|
||||
* properties from the {@code GroovyBeanDefinitionReader} itself
|
||||
* </ul>
|
||||
*/
|
||||
public Object getProperty(String name) {
|
||||
@@ -670,7 +686,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
|
||||
private GroovyDynamicElementReader createDynamicElementReader(String namespace) {
|
||||
XmlReaderContext readerContext = this.xmlBeanDefinitionReader.createReaderContext(new DescriptiveResource("Groovy"));
|
||||
XmlReaderContext readerContext = this.groovyDslXmlBeanDefinitionReader.createReaderContext(new DescriptiveResource(
|
||||
"Groovy"));
|
||||
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
|
||||
boolean decorating = (this.currentBeanDefinition != null);
|
||||
if (!decorating) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -78,6 +78,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Stephane Nicoll
|
||||
* @since 15 April 2001
|
||||
* @see #registerCustomEditor
|
||||
* @see #setPropertyValues
|
||||
@@ -978,6 +979,14 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
}
|
||||
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),
|
||||
requiredType, TypeDescriptor.nested(property(pd), tokens.keys.length));
|
||||
int length = Array.getLength(propValue);
|
||||
if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
|
||||
Class<?> componentType = propValue.getClass().getComponentType();
|
||||
Object newArray = Array.newInstance(componentType, arrayIndex + 1);
|
||||
System.arraycopy(propValue, 0, newArray, 0, length);
|
||||
setPropertyValue(actualName, newArray);
|
||||
propValue = getPropertyValue(actualName);
|
||||
}
|
||||
Array.set(propValue, arrayIndex, convertedValue);
|
||||
}
|
||||
catch (IndexOutOfBoundsException ex) {
|
||||
@@ -1046,7 +1055,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
else {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Property referenced in indexed property path '" + propertyName +
|
||||
"' is neither an array nor a List nor a Map; returned value was [" + pv.getValue() + "]");
|
||||
"' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,24 +17,31 @@
|
||||
package org.springframework.beans;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Helper class for calculating bean property matches, according to.
|
||||
* Used by BeanWrapperImpl to suggest alternatives for an invalid property name.
|
||||
* Helper class for calculating property matches, according to a configurable
|
||||
* distance. Provide the list of potential matches and an easy way to generate
|
||||
* an error message. Works for both java bean properties and fields.
|
||||
* <p>
|
||||
* Mainly for use within the framework and in particular the binding facility
|
||||
*
|
||||
* @author Alef Arendsen
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.0
|
||||
* @see #forProperty(String, Class)
|
||||
* @see #forField(String, Class)
|
||||
*/
|
||||
final class PropertyMatches {
|
||||
public abstract class PropertyMatches {
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Static section
|
||||
@@ -60,7 +67,26 @@ final class PropertyMatches {
|
||||
* @param maxDistance the maximum property distance allowed for matches
|
||||
*/
|
||||
public static PropertyMatches forProperty(String propertyName, Class<?> beanClass, int maxDistance) {
|
||||
return new PropertyMatches(propertyName, beanClass, maxDistance);
|
||||
return new BeanPropertyMatches(propertyName, beanClass, maxDistance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create PropertyMatches for the given field property.
|
||||
* @param propertyName the name of the field to find possible matches for
|
||||
* @param beanClass the bean class to search for matches
|
||||
*/
|
||||
public static PropertyMatches forField(String propertyName, Class<?> beanClass) {
|
||||
return forField(propertyName, beanClass, DEFAULT_MAX_DISTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create PropertyMatches for the given field property.
|
||||
* @param propertyName the name of the field to find possible matches for
|
||||
* @param beanClass the bean class to search for matches
|
||||
* @param maxDistance the maximum property distance allowed for matches
|
||||
*/
|
||||
public static PropertyMatches forField(String propertyName, Class<?> beanClass, int maxDistance) {
|
||||
return new FieldPropertyMatches(propertyName, beanClass, maxDistance);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,13 +100,19 @@ final class PropertyMatches {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new PropertyMatches instance for the given property.
|
||||
* Create a new PropertyMatches instance for the given property and possible matches.
|
||||
*/
|
||||
private PropertyMatches(String propertyName, Class<?> beanClass, int maxDistance) {
|
||||
private PropertyMatches(String propertyName, String[] possibleMatches) {
|
||||
this.propertyName = propertyName;
|
||||
this.possibleMatches = calculateMatches(BeanUtils.getPropertyDescriptors(beanClass), maxDistance);
|
||||
this.possibleMatches = possibleMatches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the requested property.
|
||||
*/
|
||||
public String getPropertyName() {
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the calculated possible matches.
|
||||
@@ -93,53 +125,21 @@ final class PropertyMatches {
|
||||
* Build an error message for the given invalid property name,
|
||||
* indicating the possible property matches.
|
||||
*/
|
||||
public String buildErrorMessage() {
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append("Bean property '");
|
||||
msg.append(this.propertyName);
|
||||
msg.append("' is not writable or has an invalid setter method. ");
|
||||
public abstract String buildErrorMessage();
|
||||
|
||||
if (ObjectUtils.isEmpty(this.possibleMatches)) {
|
||||
msg.append("Does the parameter type of the setter match the return type of the getter?");
|
||||
}
|
||||
else {
|
||||
msg.append("Did you mean ");
|
||||
for (int i = 0; i < this.possibleMatches.length; i++) {
|
||||
msg.append('\'');
|
||||
msg.append(this.possibleMatches[i]);
|
||||
if (i < this.possibleMatches.length - 2) {
|
||||
msg.append("', ");
|
||||
}
|
||||
else if (i == this.possibleMatches.length - 2){
|
||||
msg.append("', or ");
|
||||
}
|
||||
}
|
||||
msg.append("'?");
|
||||
}
|
||||
return msg.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate possible property alternatives for the given property and
|
||||
* class. Internally uses the {@code getStringDistance} method, which
|
||||
* in turn uses the Levenshtein algorithm to determine the distance between
|
||||
* two Strings.
|
||||
* @param propertyDescriptors the JavaBeans property descriptors to search
|
||||
* @param maxDistance the maximum distance to accept
|
||||
*/
|
||||
private String[] calculateMatches(PropertyDescriptor[] propertyDescriptors, int maxDistance) {
|
||||
List<String> candidates = new ArrayList<String>();
|
||||
for (PropertyDescriptor pd : propertyDescriptors) {
|
||||
if (pd.getWriteMethod() != null) {
|
||||
String possibleAlternative = pd.getName();
|
||||
if (calculateStringDistance(this.propertyName, possibleAlternative) <= maxDistance) {
|
||||
candidates.add(possibleAlternative);
|
||||
}
|
||||
protected void appendHintMessage(StringBuilder msg) {
|
||||
msg.append("Did you mean ");
|
||||
for (int i = 0; i < this.possibleMatches.length; i++) {
|
||||
msg.append('\'');
|
||||
msg.append(this.possibleMatches[i]);
|
||||
if (i < this.possibleMatches.length - 2) {
|
||||
msg.append("', ");
|
||||
}
|
||||
else if (i == this.possibleMatches.length - 2) {
|
||||
msg.append("', or ");
|
||||
}
|
||||
}
|
||||
Collections.sort(candidates);
|
||||
return StringUtils.toStringArray(candidates);
|
||||
msg.append("'?");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,7 +149,7 @@ final class PropertyMatches {
|
||||
* @param s2 the second String
|
||||
* @return the distance value
|
||||
*/
|
||||
private int calculateStringDistance(String s1, String s2) {
|
||||
private static int calculateStringDistance(String s1, String s2) {
|
||||
if (s1.length() == 0) {
|
||||
return s2.length();
|
||||
}
|
||||
@@ -184,4 +184,93 @@ final class PropertyMatches {
|
||||
return d[s1.length()][s2.length()];
|
||||
}
|
||||
|
||||
private static class BeanPropertyMatches extends PropertyMatches {
|
||||
|
||||
private BeanPropertyMatches(String propertyName, Class<?> beanClass, int maxDistance) {
|
||||
super(propertyName, calculateMatches(propertyName,
|
||||
BeanUtils.getPropertyDescriptors(beanClass), maxDistance));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate possible property alternatives for the given property and
|
||||
* class. Internally uses the {@code getStringDistance} method, which
|
||||
* in turn uses the Levenshtein algorithm to determine the distance between
|
||||
* two Strings.
|
||||
* @param propertyDescriptors the JavaBeans property descriptors to search
|
||||
* @param maxDistance the maximum distance to accept
|
||||
*/
|
||||
private static String[] calculateMatches(String propertyName, PropertyDescriptor[] propertyDescriptors, int maxDistance) {
|
||||
List<String> candidates = new ArrayList<String>();
|
||||
for (PropertyDescriptor pd : propertyDescriptors) {
|
||||
if (pd.getWriteMethod() != null) {
|
||||
String possibleAlternative = pd.getName();
|
||||
if (calculateStringDistance(propertyName, possibleAlternative) <= maxDistance) {
|
||||
candidates.add(possibleAlternative);
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(candidates);
|
||||
return StringUtils.toStringArray(candidates);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String buildErrorMessage() {
|
||||
String propertyName = getPropertyName();
|
||||
String[] possibleMatches = getPossibleMatches();
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append("Bean property '");
|
||||
msg.append(propertyName);
|
||||
msg.append("' is not writable or has an invalid setter method. ");
|
||||
|
||||
if (ObjectUtils.isEmpty(possibleMatches)) {
|
||||
msg.append("Does the parameter type of the setter match the return type of the getter?");
|
||||
}
|
||||
else {
|
||||
appendHintMessage(msg);
|
||||
}
|
||||
return msg.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class FieldPropertyMatches extends PropertyMatches {
|
||||
|
||||
private FieldPropertyMatches(String propertyName, Class<?> beanClass, int maxDistance) {
|
||||
super(propertyName, calculateMatches(propertyName, beanClass, maxDistance));
|
||||
}
|
||||
|
||||
private static String[] calculateMatches(final String propertyName, Class<?> beanClass, final int maxDistance) {
|
||||
final List<String> candidates = new ArrayList<String>();
|
||||
ReflectionUtils.doWithFields(beanClass, new ReflectionUtils.FieldCallback() {
|
||||
@Override
|
||||
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
|
||||
String possibleAlternative = field.getName();
|
||||
if (calculateStringDistance(propertyName, possibleAlternative) <= maxDistance) {
|
||||
candidates.add(possibleAlternative);
|
||||
}
|
||||
}
|
||||
});
|
||||
Collections.sort(candidates);
|
||||
return StringUtils.toStringArray(candidates);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String buildErrorMessage() {
|
||||
String propertyName = getPropertyName();
|
||||
String[] possibleMatches = getPossibleMatches();
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append("Bean property '");
|
||||
msg.append(propertyName);
|
||||
msg.append("' has no matching field. ");
|
||||
|
||||
if (!ObjectUtils.isEmpty(possibleMatches)) {
|
||||
appendHintMessage(msg);
|
||||
}
|
||||
return msg.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -204,7 +204,7 @@ class TypeConverterDelegate {
|
||||
if (Object.class.equals(requiredType)) {
|
||||
return (T) convertedValue;
|
||||
}
|
||||
if (requiredType.isArray()) {
|
||||
else if (requiredType.isArray()) {
|
||||
// Array required -> apply appropriate conversion of elements.
|
||||
if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {
|
||||
convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
|
||||
@@ -339,7 +339,6 @@ class TypeConverterDelegate {
|
||||
catch (Throwable ex) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Field [" + convertedValue + "] isn't an enum value", ex);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -114,6 +114,7 @@ public interface BeanFactory {
|
||||
*/
|
||||
String FACTORY_BEAN_PREFIX = "&";
|
||||
|
||||
|
||||
/**
|
||||
* Return an instance, which may be shared or independent, of the specified bean.
|
||||
* <p>This method allows a Spring BeanFactory to be used as a replacement for the
|
||||
@@ -202,6 +203,7 @@ public interface BeanFactory {
|
||||
*/
|
||||
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
|
||||
|
||||
|
||||
/**
|
||||
* Does this bean factory contain a bean definition or externally registered singleton
|
||||
* instance with the given name?
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,12 +38,15 @@ import java.lang.annotation.Target;
|
||||
* container to fill them in at runtime. In both cases, the container will generate
|
||||
* runtime subclasses of the method's containing class via CGLIB, which is why such
|
||||
* lookup methods can only work on beans that the container instantiates through
|
||||
* regular constructors (i.e. lookup methods cannot get replaced on beans returned
|
||||
* from factory methods where we can't dynamically provide a subclass for them).
|
||||
* regular constructors: i.e. lookup methods cannot get replaced on beans returned
|
||||
* from factory methods where we cannot dynamically provide a subclass for them.
|
||||
*
|
||||
* <p>Note: When used with component scanning or any other mechanism that filters
|
||||
* out abstract beans, provide stub implementations of your lookup methods to be
|
||||
* able to declare them as concrete classes.
|
||||
* <p><b>Concrete limitations in typical Spring configuration scenarios:</b>
|
||||
* When used with component scanning or any other mechanism that filters out abstract
|
||||
* beans, provide stub implementations of your lookup methods to be able to declare
|
||||
* them as concrete classes. And please remember that lookup methods won't work on
|
||||
* beans returned from {@code @Bean} methods in configuration classes; you'll have
|
||||
* to resort to {@code @Inject Provider<TargetBean>} or the like instead.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -219,8 +219,7 @@ public class PropertyPlaceholderConfigurer extends PlaceholderConfigurerSupport
|
||||
throws BeansException {
|
||||
|
||||
StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);
|
||||
|
||||
this.doProcessProperties(beanFactoryToProcess, valueResolver);
|
||||
doProcessProperties(beanFactoryToProcess, valueResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+18
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,7 @@
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -35,6 +35,7 @@ import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.constructor.Constructor;
|
||||
import org.yaml.snakeyaml.nodes.MappingNode;
|
||||
import org.yaml.snakeyaml.parser.ParserException;
|
||||
import org.yaml.snakeyaml.reader.UnicodeReader;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -130,9 +131,10 @@ public abstract class YamlProcessor {
|
||||
* Properties. Depending on the {@link #setResolutionMethod(ResolutionMethod)} not all
|
||||
* of the documents will be parsed.
|
||||
* @param callback a callback to delegate to once matching documents are found
|
||||
* @see #createYaml()
|
||||
*/
|
||||
protected void process(MatchCallback callback) {
|
||||
Yaml yaml = new Yaml(new StrictMapAppenderConstructor());
|
||||
Yaml yaml = createYaml();
|
||||
for (Resource resource : this.resources) {
|
||||
boolean found = process(callback, yaml, resource);
|
||||
if (this.resolutionMethod == ResolutionMethod.FIRST_FOUND && found) {
|
||||
@@ -141,15 +143,22 @@ public abstract class YamlProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the {@link Yaml} instance to use.
|
||||
*/
|
||||
protected Yaml createYaml() {
|
||||
return new Yaml(new StrictMapAppenderConstructor());
|
||||
}
|
||||
|
||||
private boolean process(MatchCallback callback, Yaml yaml, Resource resource) {
|
||||
int count = 0;
|
||||
try {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Loading from YAML: " + resource);
|
||||
}
|
||||
InputStream stream = resource.getInputStream();
|
||||
Reader reader = new UnicodeReader(resource.getInputStream());
|
||||
try {
|
||||
for (Object object : yaml.loadAll(stream)) {
|
||||
for (Object object : yaml.loadAll(reader)) {
|
||||
if (object != null && process(asMap(object), callback)) {
|
||||
count++;
|
||||
if (this.resolutionMethod == ResolutionMethod.FIRST_FOUND) {
|
||||
@@ -163,7 +172,7 @@ public abstract class YamlProcessor {
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stream.close();
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
@@ -331,7 +340,7 @@ public abstract class YamlProcessor {
|
||||
/**
|
||||
* Status returned from {@link DocumentMatcher#matches(java.util.Properties)}
|
||||
*/
|
||||
public static enum MatchStatus {
|
||||
public enum MatchStatus {
|
||||
|
||||
/**
|
||||
* A match was found.
|
||||
@@ -360,7 +369,7 @@ public abstract class YamlProcessor {
|
||||
/**
|
||||
* Method to use for resolving resources.
|
||||
*/
|
||||
public static enum ResolutionMethod {
|
||||
public enum ResolutionMethod {
|
||||
|
||||
/**
|
||||
* Replace values from earlier in the list.
|
||||
@@ -382,7 +391,7 @@ public abstract class YamlProcessor {
|
||||
/**
|
||||
* A specialized {@link Constructor} that checks for duplicate keys.
|
||||
*/
|
||||
private static class StrictMapAppenderConstructor extends Constructor {
|
||||
protected static class StrictMapAppenderConstructor extends Constructor {
|
||||
|
||||
public StrictMapAppenderConstructor() {
|
||||
super();
|
||||
|
||||
+8
@@ -897,6 +897,14 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
instance = bw.getWrappedInstance();
|
||||
}
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
// Can only happen when getting a FactoryBean.
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Bean creation exception on non-singleton FactoryBean type check: " + ex);
|
||||
}
|
||||
onSuppressedException(ex);
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
// Finished partial creation of this bean.
|
||||
afterPrototypeCreation(beanName);
|
||||
|
||||
+10
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1422,9 +1422,15 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
return getTypeForFactoryBean(factoryBean);
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
// Can only happen when getting a FactoryBean.
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Bean creation exception on FactoryBean type check: " + ex);
|
||||
if (ex instanceof BeanCurrentlyInCreationException) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Bean currently in creation on FactoryBean type check: " + ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Bean creation exception on FactoryBean type check: " + ex);
|
||||
}
|
||||
}
|
||||
onSuppressedException(ex);
|
||||
return null;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -279,7 +279,7 @@ public class BeanDefinitionBuilder {
|
||||
*/
|
||||
public BeanDefinitionBuilder addDependsOn(String beanName) {
|
||||
if (this.beanDefinition.getDependsOn() == null) {
|
||||
this.beanDefinition.setDependsOn(new String[] {beanName});
|
||||
this.beanDefinition.setDependsOn(beanName);
|
||||
}
|
||||
else {
|
||||
String[] added = ObjectUtils.addObjectToArray(this.beanDefinition.getDependsOn(), beanName);
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -150,8 +150,8 @@ public class BeanDefinitionReaderUtils {
|
||||
// Register aliases for bean name, if any.
|
||||
String[] aliases = definitionHolder.getAliases();
|
||||
if (aliases != null) {
|
||||
for (String aliase : aliases) {
|
||||
registry.registerAlias(beanName, aliase);
|
||||
for (String alias : aliases) {
|
||||
registry.registerAlias(beanName, alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -323,7 +323,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of ListableBeanFactory interface
|
||||
// Implementation of remaining BeanFactory methods
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
@@ -562,17 +562,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) {
|
||||
Map<String, Object> results = new LinkedHashMap<String, Object>();
|
||||
for (String beanName : this.beanDefinitionNames) {
|
||||
BeanDefinition beanDefinition = getBeanDefinition(beanName);
|
||||
if (!beanDefinition.isAbstract() && findAnnotationOnBean(beanName, annotationType) != null) {
|
||||
results.put(beanName, getBean(beanName));
|
||||
}
|
||||
}
|
||||
for (String beanName : this.manualSingletonNames) {
|
||||
if (!results.containsKey(beanName) && findAnnotationOnBean(beanName, annotationType) != null) {
|
||||
results.put(beanName, getBean(beanName));
|
||||
}
|
||||
String[] beanNames = getBeanNamesForAnnotation(annotationType);
|
||||
Map<String, Object> results = new LinkedHashMap<String, Object>(beanNames.length);
|
||||
for (String beanName : beanNames) {
|
||||
results.put(beanName, getBean(beanName));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
@@ -811,7 +804,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
|
||||
if (oldBeanDefinition != null) {
|
||||
if (!this.allowBeanDefinitionOverriding) {
|
||||
if (!isAllowBeanDefinitionOverriding()) {
|
||||
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
|
||||
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
|
||||
"': There is already [" + oldBeanDefinition + "] bound.");
|
||||
@@ -820,7 +813,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
|
||||
if (this.logger.isWarnEnabled()) {
|
||||
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
|
||||
" with a framework-generated bean definition ': replacing [" +
|
||||
"' with a framework-generated bean definition: replacing [" +
|
||||
oldBeanDefinition + "] with [" + beanDefinition + "]");
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -607,13 +607,13 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the singleton mutex to subclasses.
|
||||
* Exposes the singleton mutex to subclasses and external collaborators.
|
||||
* <p>Subclasses should synchronize on the given Object if they perform
|
||||
* any sort of extended singleton creation phase. In particular, subclasses
|
||||
* should <i>not</i> have their own mutexes involved in singleton creation,
|
||||
* to avoid the potential for deadlocks in lazy-init situations.
|
||||
*/
|
||||
protected final Object getSingletonMutex() {
|
||||
public final Object getSingletonMutex() {
|
||||
return this.singletonObjects;
|
||||
}
|
||||
|
||||
|
||||
+22
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -49,12 +49,13 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public abstract class AbstractBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
/** Constant for the id attribute */
|
||||
/** Constant for the "id" attribute */
|
||||
public static final String ID_ATTRIBUTE = "id";
|
||||
|
||||
/** Constant for the name attribute */
|
||||
/** Constant for the "name" attribute */
|
||||
public static final String NAME_ATTRIBUTE = "name";
|
||||
|
||||
|
||||
@Override
|
||||
public final BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
AbstractBeanDefinition definition = parseInternal(element, parserContext);
|
||||
@@ -66,10 +67,12 @@ public abstract class AbstractBeanDefinitionParser implements BeanDefinitionPars
|
||||
"Id is required for element '" + parserContext.getDelegate().getLocalName(element)
|
||||
+ "' when used as a top-level tag", element);
|
||||
}
|
||||
String[] aliases = new String[0];
|
||||
String name = element.getAttribute(NAME_ATTRIBUTE);
|
||||
if (StringUtils.hasLength(name)) {
|
||||
aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
|
||||
String[] aliases = null;
|
||||
if (shouldParseNameAsAliases()) {
|
||||
String name = element.getAttribute(NAME_ATTRIBUTE);
|
||||
if (StringUtils.hasLength(name)) {
|
||||
aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
|
||||
}
|
||||
}
|
||||
BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
|
||||
registerBeanDefinition(holder, parserContext.getRegistry());
|
||||
@@ -170,7 +173,18 @@ public abstract class AbstractBeanDefinitionParser implements BeanDefinitionPars
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls whether this parser is supposed to fire a
|
||||
* Determine whether the element's "name" attribute should get parsed as
|
||||
* bean definition aliases, i.e. alternative bean definition names.
|
||||
* <p>The default implementation returns {@code true}.
|
||||
* @return whether the parser should evaluate the "name" attribute as aliases
|
||||
* @since 4.1.5
|
||||
*/
|
||||
protected boolean shouldParseNameAsAliases() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether this parser is supposed to fire a
|
||||
* {@link org.springframework.beans.factory.parsing.BeanComponentDefinition}
|
||||
* event after parsing the bean definition.
|
||||
* <p>This implementation returns {@code true} by default; that is,
|
||||
|
||||
+26
-27
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.beans.factory.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -45,7 +44,9 @@ public class BeansDtdResolver implements EntityResolver {
|
||||
|
||||
private static final String DTD_EXTENSION = ".dtd";
|
||||
|
||||
private static final String[] DTD_NAMES = {"spring-beans-2.0", "spring-beans"};
|
||||
private static final String DTD_FILENAME = "spring-beans-2.0";
|
||||
|
||||
private static final String DTD_NAME = "spring-beans";
|
||||
|
||||
private static final Log logger = LogFactory.getLog(BeansDtdResolver.class);
|
||||
|
||||
@@ -58,30 +59,28 @@ public class BeansDtdResolver implements EntityResolver {
|
||||
}
|
||||
if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {
|
||||
int lastPathSeparator = systemId.lastIndexOf("/");
|
||||
for (String DTD_NAME : DTD_NAMES) {
|
||||
int dtdNameStart = systemId.indexOf(DTD_NAME);
|
||||
if (dtdNameStart > lastPathSeparator) {
|
||||
String dtdFile = systemId.substring(dtdNameStart);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Trying to locate [" + dtdFile + "] in Spring jar");
|
||||
}
|
||||
try {
|
||||
Resource resource = new ClassPathResource(dtdFile, getClass());
|
||||
InputSource source = new InputSource(resource.getInputStream());
|
||||
source.setPublicId(publicId);
|
||||
source.setSystemId(systemId);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found beans DTD [" + systemId + "] in classpath: " + dtdFile);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in class path", ex);
|
||||
}
|
||||
}
|
||||
|
||||
int dtdNameStart = systemId.indexOf(DTD_NAME);
|
||||
if (dtdNameStart > lastPathSeparator) {
|
||||
String dtdFile = DTD_FILENAME + DTD_EXTENSION;
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Trying to locate [" + dtdFile + "] in Spring jar on classpath");
|
||||
}
|
||||
try {
|
||||
Resource resource = new ClassPathResource(dtdFile, getClass());
|
||||
InputSource source = new InputSource(resource.getInputStream());
|
||||
source.setPublicId(publicId);
|
||||
source.setSystemId(systemId);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found beans DTD [" + systemId + "] in classpath: " + dtdFile);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in classpath", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +91,7 @@ public class BeansDtdResolver implements EntityResolver {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EntityResolver for DTDs " + Arrays.toString(DTD_NAMES);
|
||||
return "EntityResolver for spring-beans DTD";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -95,6 +95,7 @@ public class CustomBooleanEditor extends PropertyEditorSupport {
|
||||
this.allowEmpty = allowEmpty;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
String input = (text != null ? text.trim() : null);
|
||||
@@ -102,20 +103,20 @@ public class CustomBooleanEditor extends PropertyEditorSupport {
|
||||
// Treat empty String as null value.
|
||||
setValue(null);
|
||||
}
|
||||
else if (this.trueString != null && input.equalsIgnoreCase(this.trueString)) {
|
||||
else if (this.trueString != null && this.trueString.equalsIgnoreCase(input)) {
|
||||
setValue(Boolean.TRUE);
|
||||
}
|
||||
else if (this.falseString != null && input.equalsIgnoreCase(this.falseString)) {
|
||||
else if (this.falseString != null && this.falseString.equalsIgnoreCase(input)) {
|
||||
setValue(Boolean.FALSE);
|
||||
}
|
||||
else if (this.trueString == null &&
|
||||
(input.equalsIgnoreCase(VALUE_TRUE) || input.equalsIgnoreCase(VALUE_ON) ||
|
||||
input.equalsIgnoreCase(VALUE_YES) || input.equals(VALUE_1))) {
|
||||
(VALUE_TRUE.equalsIgnoreCase(input) || VALUE_ON.equalsIgnoreCase(input) ||
|
||||
VALUE_YES.equalsIgnoreCase(input) || VALUE_1.equals(input))) {
|
||||
setValue(Boolean.TRUE);
|
||||
}
|
||||
else if (this.falseString == null &&
|
||||
(input.equalsIgnoreCase(VALUE_FALSE) || input.equalsIgnoreCase(VALUE_OFF) ||
|
||||
input.equalsIgnoreCase(VALUE_NO) || input.equals(VALUE_0))) {
|
||||
(VALUE_FALSE.equalsIgnoreCase(input) || VALUE_OFF.equalsIgnoreCase(input) ||
|
||||
VALUE_NO.equalsIgnoreCase(input) || VALUE_0.equals(input))) {
|
||||
setValue(Boolean.FALSE);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -518,6 +518,36 @@ public final class BeanWrapperTests extends AbstractConfigurablePropertyAccessor
|
||||
assertTrue("correct values", pt.stringArray[0].equals("a1") && pt.stringArray[1].equals("b2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringArrayAutoGrow() throws Exception {
|
||||
StringArrayBean target = new StringArrayBean();
|
||||
BeanWrapper bw = new BeanWrapperImpl(target);
|
||||
bw.setAutoGrowNestedPaths(true);
|
||||
|
||||
bw.setPropertyValue("array[0]", "Test0");
|
||||
assertEquals(1, target.getArray().length);
|
||||
|
||||
bw.setPropertyValue("array[2]", "Test2");
|
||||
assertEquals(3, target.getArray().length);
|
||||
assertTrue("correct values", target.getArray()[0].equals("Test0") && target.getArray()[1] == null &&
|
||||
target.getArray()[2].equals("Test2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrimitiveArrayAutoGrow() throws Exception {
|
||||
PrimitiveArrayBean target = new PrimitiveArrayBean();
|
||||
BeanWrapper bw = new BeanWrapperImpl(target);
|
||||
bw.setAutoGrowNestedPaths(true);
|
||||
|
||||
bw.setPropertyValue("array[0]", 1);
|
||||
assertEquals(1, target.getArray().length);
|
||||
|
||||
bw.setPropertyValue("array[2]", 3);
|
||||
assertEquals(3, target.getArray().length);
|
||||
assertTrue("correct values", target.getArray()[0] == 1 && target.getArray()[1] == 0 &&
|
||||
target.getArray()[2] == 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringPropertyWithCustomEditor() throws Exception {
|
||||
TestBean tb = new TestBean();
|
||||
@@ -1723,6 +1753,20 @@ public final class BeanWrapperTests extends AbstractConfigurablePropertyAccessor
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class StringArrayBean {
|
||||
|
||||
private String[] array;
|
||||
|
||||
public String[] getArray() {
|
||||
return array;
|
||||
}
|
||||
|
||||
public void setArray(String[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class NumberPropertyBean {
|
||||
|
||||
@@ -841,19 +841,24 @@ public class ExtendedBeanInfoTests {
|
||||
public String getAddress(int index){ return null; }
|
||||
}
|
||||
|
||||
{ // baseline. ExtendedBeanInfo needs to behave exactly like the following
|
||||
// Baseline: ExtendedBeanInfo needs to behave exactly like the following...
|
||||
boolean hasReadMethod;
|
||||
boolean hasWriteMethod;
|
||||
boolean hasIndexedReadMethod;
|
||||
boolean hasIndexedWriteMethod;
|
||||
{
|
||||
BeanInfo bi = Introspector.getBeanInfo(A.class);
|
||||
assertThat(hasReadMethodForProperty(bi, "address"), is(false));
|
||||
assertThat(hasWriteMethodForProperty(bi, "address"), is(false));
|
||||
assertThat(hasIndexedReadMethodForProperty(bi, "address"), is(true));
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "address"), is(true));
|
||||
hasReadMethod = hasReadMethodForProperty(bi, "address");
|
||||
hasWriteMethod = hasWriteMethodForProperty(bi, "address");
|
||||
hasIndexedReadMethod = hasIndexedReadMethodForProperty(bi, "address");
|
||||
hasIndexedWriteMethod = hasIndexedWriteMethodForProperty(bi, "address");
|
||||
}
|
||||
{
|
||||
BeanInfo bi = new ExtendedBeanInfo(Introspector.getBeanInfo(A.class));
|
||||
assertThat(hasReadMethodForProperty(bi, "address"), is(false));
|
||||
assertThat(hasWriteMethodForProperty(bi, "address"), is(false));
|
||||
assertThat(hasIndexedReadMethodForProperty(bi, "address"), is(true));
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "address"), is(true));
|
||||
assertEquals(hasReadMethodForProperty(bi, "address"), hasReadMethod);
|
||||
assertEquals(hasWriteMethodForProperty(bi, "address"), hasWriteMethod);
|
||||
assertEquals(hasIndexedReadMethodForProperty(bi, "address"), hasIndexedReadMethod);
|
||||
assertEquals(hasIndexedWriteMethodForProperty(bi, "address"), hasIndexedWriteMethod);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests for {@link PropertyMatches}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class PropertyMatchesTests {
|
||||
|
||||
@Test
|
||||
public void simpleBeanPropertyTypo() {
|
||||
PropertyMatches matches = PropertyMatches.forProperty("naem", SampleBeanProperties.class);
|
||||
assertThat(matches.getPossibleMatches(), hasItemInArray("name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void complexBeanPropertyTypo() {
|
||||
PropertyMatches matches = PropertyMatches.forProperty("desriptn", SampleBeanProperties.class);
|
||||
assertThat(matches.getPossibleMatches(), emptyArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unknownBeanProperty() {
|
||||
PropertyMatches matches = PropertyMatches.forProperty("unknown", SampleBeanProperties.class);
|
||||
assertThat(matches.getPossibleMatches(), emptyArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void severalMatchesBeanProperty() {
|
||||
PropertyMatches matches = PropertyMatches.forProperty("counter", SampleBeanProperties.class);
|
||||
assertThat(matches.getPossibleMatches(), hasItemInArray("counter1"));
|
||||
assertThat(matches.getPossibleMatches(), hasItemInArray("counter2"));
|
||||
assertThat(matches.getPossibleMatches(), hasItemInArray("counter3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleBeanPropertyErrorMessage() {
|
||||
PropertyMatches matches = PropertyMatches.forProperty("naem", SampleBeanProperties.class);
|
||||
String msg = matches.buildErrorMessage();
|
||||
assertThat(msg, containsString("naem"));
|
||||
assertThat(msg, containsString("name"));
|
||||
assertThat(msg, containsString("setter"));
|
||||
assertThat(msg, not(containsString("field")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void complexBeanPropertyErrorMessage() {
|
||||
PropertyMatches matches = PropertyMatches.forProperty("counter", SampleBeanProperties.class);
|
||||
String msg = matches.buildErrorMessage();
|
||||
assertThat(msg, containsString("counter"));
|
||||
assertThat(msg, containsString("counter1"));
|
||||
assertThat(msg, containsString("counter2"));
|
||||
assertThat(msg, containsString("counter3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleFieldPropertyTypo() {
|
||||
PropertyMatches matches = PropertyMatches.forField("naem", SampleFieldProperties.class);
|
||||
assertThat(matches.getPossibleMatches(), hasItemInArray("name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void complexFieldPropertyTypo() {
|
||||
PropertyMatches matches = PropertyMatches.forField("desriptn", SampleFieldProperties.class);
|
||||
assertThat(matches.getPossibleMatches(), emptyArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unknownFieldProperty() {
|
||||
PropertyMatches matches = PropertyMatches.forField("unknown", SampleFieldProperties.class);
|
||||
assertThat(matches.getPossibleMatches(), emptyArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void severalMatchesFieldProperty() {
|
||||
PropertyMatches matches = PropertyMatches.forField("counter", SampleFieldProperties.class);
|
||||
assertThat(matches.getPossibleMatches(), hasItemInArray("counter1"));
|
||||
assertThat(matches.getPossibleMatches(), hasItemInArray("counter2"));
|
||||
assertThat(matches.getPossibleMatches(), hasItemInArray("counter3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleFieldPropertyErrorMessage() {
|
||||
PropertyMatches matches = PropertyMatches.forField("naem", SampleFieldProperties.class);
|
||||
String msg = matches.buildErrorMessage();
|
||||
assertThat(msg, containsString("naem"));
|
||||
assertThat(msg, containsString("name"));
|
||||
assertThat(msg, containsString("field"));
|
||||
assertThat(msg, not(containsString("setter")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void complexFieldPropertyErrorMessage() {
|
||||
PropertyMatches matches = PropertyMatches.forField("counter", SampleFieldProperties.class);
|
||||
String msg = matches.buildErrorMessage();
|
||||
assertThat(msg, containsString("counter"));
|
||||
assertThat(msg, containsString("counter1"));
|
||||
assertThat(msg, containsString("counter2"));
|
||||
assertThat(msg, containsString("counter3"));
|
||||
}
|
||||
|
||||
|
||||
private static class SampleBeanProperties {
|
||||
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
private int counter1;
|
||||
|
||||
private int counter2;
|
||||
|
||||
private int counter3;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getCounter1() {
|
||||
return counter1;
|
||||
}
|
||||
|
||||
public void setCounter1(int counter1) {
|
||||
this.counter1 = counter1;
|
||||
}
|
||||
|
||||
public int getCounter2() {
|
||||
return counter2;
|
||||
}
|
||||
|
||||
public void setCounter2(int counter2) {
|
||||
this.counter2 = counter2;
|
||||
}
|
||||
|
||||
public int getCounter3() {
|
||||
return counter3;
|
||||
}
|
||||
|
||||
public void setCounter3(int counter3) {
|
||||
this.counter3 = counter3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class SampleFieldProperties {
|
||||
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
private int counter1;
|
||||
|
||||
private int counter2;
|
||||
|
||||
private int counter3;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+29
-34
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,8 +23,6 @@ import java.util.Map;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
@@ -53,16 +51,16 @@ public final class BeanFactoryUtilsTests {
|
||||
private static final Resource LEAF_CONTEXT = qualifiedResource(CLASS, "leaf.xml");
|
||||
private static final Resource DEPENDENT_BEANS_CONTEXT = qualifiedResource(CLASS, "dependentBeans.xml");
|
||||
|
||||
private ConfigurableListableBeanFactory listableBeanFactory;
|
||||
private DefaultListableBeanFactory listableBeanFactory;
|
||||
|
||||
private DefaultListableBeanFactory dependentBeansFactory;
|
||||
|
||||
private ConfigurableListableBeanFactory dependentBeansBF;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
// Interesting hierarchical factory to test counts.
|
||||
// Slow to read so we cache it.
|
||||
|
||||
|
||||
DefaultListableBeanFactory grandParent = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(grandParent).loadBeanDefinitions(ROOT_CONTEXT);
|
||||
DefaultListableBeanFactory parent = new DefaultListableBeanFactory(grandParent);
|
||||
@@ -70,12 +68,13 @@ public final class BeanFactoryUtilsTests {
|
||||
DefaultListableBeanFactory child = new DefaultListableBeanFactory(parent);
|
||||
new XmlBeanDefinitionReader(child).loadBeanDefinitions(LEAF_CONTEXT);
|
||||
|
||||
this.dependentBeansBF = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader((BeanDefinitionRegistry) this.dependentBeansBF).loadBeanDefinitions(DEPENDENT_BEANS_CONTEXT);
|
||||
dependentBeansBF.preInstantiateSingletons();
|
||||
this.dependentBeansFactory = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(this.dependentBeansFactory).loadBeanDefinitions(DEPENDENT_BEANS_CONTEXT);
|
||||
dependentBeansFactory.preInstantiateSingletons();
|
||||
this.listableBeanFactory = child;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHierarchicalCountBeansWithNonHierarchicalFactory() {
|
||||
StaticListableBeanFactory lbf = new StaticListableBeanFactory();
|
||||
@@ -92,22 +91,21 @@ public final class BeanFactoryUtilsTests {
|
||||
// Leaf count
|
||||
assertTrue(this.listableBeanFactory.getBeanDefinitionCount() == 1);
|
||||
// Count minus duplicate
|
||||
assertTrue("Should count 7 beans, not "
|
||||
+ BeanFactoryUtils.countBeansIncludingAncestors(this.listableBeanFactory),
|
||||
BeanFactoryUtils.countBeansIncludingAncestors(this.listableBeanFactory) == 7);
|
||||
assertTrue("Should count 7 beans, not " + BeanFactoryUtils.countBeansIncludingAncestors(this.listableBeanFactory),
|
||||
BeanFactoryUtils.countBeansIncludingAncestors(this.listableBeanFactory) == 7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHierarchicalNamesWithNoMatch() throws Exception {
|
||||
List<String> names = Arrays.asList(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory,
|
||||
NoOp.class));
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory, NoOp.class));
|
||||
assertEquals(0, names.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHierarchicalNamesWithMatchOnlyInRoot() throws Exception {
|
||||
List<String> names = Arrays.asList(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory,
|
||||
IndexedTestBean.class));
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory, IndexedTestBean.class));
|
||||
assertEquals(1, names.size());
|
||||
assertTrue(names.contains("indexedBean"));
|
||||
// Distinguish from default ListableBeanFactory behavior
|
||||
@@ -116,8 +114,8 @@ public final class BeanFactoryUtilsTests {
|
||||
|
||||
@Test
|
||||
public void testGetBeanNamesForTypeWithOverride() throws Exception {
|
||||
List<String> names = Arrays.asList(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory,
|
||||
ITestBean.class));
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class));
|
||||
// includes 2 TestBeans from FactoryBeans (DummyFactory definitions)
|
||||
assertEquals(4, names.size());
|
||||
assertTrue(names.contains("test"));
|
||||
@@ -130,7 +128,7 @@ public final class BeanFactoryUtilsTests {
|
||||
public void testNoBeansOfType() {
|
||||
StaticListableBeanFactory lbf = new StaticListableBeanFactory();
|
||||
lbf.addBean("foo", new Object());
|
||||
Map<?, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, true, false);
|
||||
Map<String, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, true, false);
|
||||
assertTrue(beans.isEmpty());
|
||||
}
|
||||
|
||||
@@ -147,7 +145,7 @@ public final class BeanFactoryUtilsTests {
|
||||
lbf.addBean("t3", t3);
|
||||
lbf.addBean("t4", t4);
|
||||
|
||||
Map<?, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, true, false);
|
||||
Map<String, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, true, false);
|
||||
assertEquals(2, beans.size());
|
||||
assertEquals(t1, beans.get("t1"));
|
||||
assertEquals(t2, beans.get("t2"));
|
||||
@@ -191,8 +189,8 @@ public final class BeanFactoryUtilsTests {
|
||||
this.listableBeanFactory.registerSingleton("t3", t3);
|
||||
this.listableBeanFactory.registerSingleton("t4", t4);
|
||||
|
||||
Map<?, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, true,
|
||||
false);
|
||||
Map<String, ?> beans =
|
||||
BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, true, false);
|
||||
assertEquals(6, beans.size());
|
||||
assertEquals(test3, beans.get("test3"));
|
||||
assertEquals(test, beans.get("test"));
|
||||
@@ -200,12 +198,9 @@ public final class BeanFactoryUtilsTests {
|
||||
assertEquals(t2, beans.get("t2"));
|
||||
assertEquals(t3.getObject(), beans.get("t3"));
|
||||
assertTrue(beans.get("t4") instanceof TestBean);
|
||||
// t3 and t4 are found here as of Spring 2.0, since they are
|
||||
// pre-registered
|
||||
// singleton instances, while testFactory1 and testFactory are *not*
|
||||
// found
|
||||
// because they are FactoryBean definitions that haven't been
|
||||
// initialized yet.
|
||||
// t3 and t4 are found here as of Spring 2.0, since they are pre-registered
|
||||
// singleton instances, while testFactory1 and testFactory are *not* found
|
||||
// because they are FactoryBean definitions that haven't been initialized yet.
|
||||
|
||||
beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, false, true);
|
||||
Object testFactory1 = this.listableBeanFactory.getBean("testFactory1");
|
||||
@@ -247,8 +242,8 @@ public final class BeanFactoryUtilsTests {
|
||||
Object test3 = this.listableBeanFactory.getBean("test3");
|
||||
Object test = this.listableBeanFactory.getBean("test");
|
||||
|
||||
Map<?, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, true,
|
||||
false);
|
||||
Map<String, ?> beans =
|
||||
BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, true, false);
|
||||
assertEquals(2, beans.size());
|
||||
assertEquals(test3, beans.get("test3"));
|
||||
assertEquals(test, beans.get("test"));
|
||||
@@ -283,25 +278,25 @@ public final class BeanFactoryUtilsTests {
|
||||
|
||||
@Test
|
||||
public void testADependencies() {
|
||||
String[] deps = this.dependentBeansBF.getDependentBeans("a");
|
||||
String[] deps = this.dependentBeansFactory.getDependentBeans("a");
|
||||
assertTrue(ObjectUtils.isEmpty(deps));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBDependencies() {
|
||||
String[] deps = this.dependentBeansBF.getDependentBeans("b");
|
||||
String[] deps = this.dependentBeansFactory.getDependentBeans("b");
|
||||
assertTrue(Arrays.equals(new String[] { "c" }, deps));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCDependencies() {
|
||||
String[] deps = this.dependentBeansBF.getDependentBeans("c");
|
||||
String[] deps = this.dependentBeansFactory.getDependentBeans("c");
|
||||
assertTrue(Arrays.equals(new String[] { "int", "long" }, deps));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntDependencies() {
|
||||
String[] deps = this.dependentBeansBF.getDependentBeans("int");
|
||||
String[] deps = this.dependentBeansFactory.getDependentBeans("int");
|
||||
assertTrue(Arrays.equals(new String[] { "buffer" }, deps));
|
||||
}
|
||||
|
||||
|
||||
+40
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -200,7 +200,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrototypeSingletonFactoryBeanIgnoredByNonEagerTypeMatching() {
|
||||
public void testSingletonFactoryBeanIgnoredByNonEagerTypeMatching() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
Properties p = new Properties();
|
||||
p.setProperty("x1.(class)", DummyFactory.class.getName());
|
||||
@@ -1340,10 +1340,10 @@ public class DefaultListableBeanFactoryTests {
|
||||
public void testDependsOnCycle() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||
bd1.setDependsOn(new String[] {"tb2"});
|
||||
bd1.setDependsOn("tb2");
|
||||
lbf.registerBeanDefinition("tb1", bd1);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
bd2.setDependsOn(new String[] {"tb1"});
|
||||
bd2.setDependsOn("tb1");
|
||||
lbf.registerBeanDefinition("tb2", bd2);
|
||||
try {
|
||||
lbf.preInstantiateSingletons();
|
||||
@@ -1361,13 +1361,13 @@ public class DefaultListableBeanFactoryTests {
|
||||
public void testImplicitDependsOnCycle() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||
bd1.setDependsOn(new String[] {"tb2"});
|
||||
bd1.setDependsOn("tb2");
|
||||
lbf.registerBeanDefinition("tb1", bd1);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
bd2.setDependsOn(new String[] {"tb3"});
|
||||
bd2.setDependsOn("tb3");
|
||||
lbf.registerBeanDefinition("tb2", bd2);
|
||||
RootBeanDefinition bd3 = new RootBeanDefinition(TestBean.class);
|
||||
bd3.setDependsOn(new String[] {"tb1"});
|
||||
bd3.setDependsOn("tb1");
|
||||
lbf.registerBeanDefinition("tb3", bd3);
|
||||
try {
|
||||
lbf.preInstantiateSingletons();
|
||||
@@ -1381,7 +1381,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected=NoSuchBeanDefinitionException.class)
|
||||
@Test(expected = NoSuchBeanDefinitionException.class)
|
||||
public void testGetBeanByTypeWithNoneFound() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
lbf.getBean(TestBean.class);
|
||||
@@ -1397,7 +1397,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
assertThat(bean.getBeanName(), equalTo("bd1"));
|
||||
}
|
||||
|
||||
@Test(expected=NoUniqueBeanDefinitionException.class)
|
||||
@Test(expected = NoUniqueBeanDefinitionException.class)
|
||||
public void testGetBeanByTypeWithAmbiguity() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||
@@ -1540,7 +1540,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanByTypeInstanceWithPrimary() throws Exception {
|
||||
public void testGetBeanByTypeInstanceWithPrimary() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = createConstructorDependencyBeanDefinition(99);
|
||||
RootBeanDefinition bd2 = createConstructorDependencyBeanDefinition(43);
|
||||
@@ -1553,7 +1553,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanByTypeInstanceWithMultiplePrimary() throws Exception {
|
||||
public void testGetBeanByTypeInstanceWithMultiplePrimary() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = createConstructorDependencyBeanDefinition(99);
|
||||
RootBeanDefinition bd2 = createConstructorDependencyBeanDefinition(43);
|
||||
@@ -1584,16 +1584,35 @@ public class DefaultListableBeanFactoryTests {
|
||||
try {
|
||||
lbf.getBean(TestBean.class, 67);
|
||||
fail("Should have thrown NoSuchBeanDefinitionException");
|
||||
} catch (NoSuchBeanDefinitionException ex) {
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
private RootBeanDefinition createConstructorDependencyBeanDefinition(int age) {
|
||||
@Test
|
||||
public void testGetBeanWithArgsNotCreatedForFactoryBeanChecking() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(ConstructorDependency.class);
|
||||
bd1.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
bd1.getConstructorArgumentValues().addGenericArgumentValue(String.valueOf(age));
|
||||
return bd1;
|
||||
lbf.registerBeanDefinition("bd1", bd1);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(ConstructorDependencyFactoryBean.class);
|
||||
bd2.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
lbf.registerBeanDefinition("bd2", bd2);
|
||||
|
||||
ConstructorDependency bean = lbf.getBean(ConstructorDependency.class, 42);
|
||||
assertThat(bean.beanName, equalTo("bd1"));
|
||||
assertThat(bean.spouseAge, equalTo(42));
|
||||
|
||||
assertEquals(1, lbf.getBeanNamesForType(ConstructorDependency.class).length);
|
||||
assertEquals(1, lbf.getBeanNamesForType(ConstructorDependencyFactoryBean.class).length);
|
||||
}
|
||||
|
||||
private RootBeanDefinition createConstructorDependencyBeanDefinition(int age) {
|
||||
RootBeanDefinition bd = new RootBeanDefinition(ConstructorDependency.class);
|
||||
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
bd.getConstructorArgumentValues().addGenericArgumentValue(String.valueOf(age));
|
||||
return bd;
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1641,7 +1660,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
* Java method names. In other words, you can't name a method
|
||||
* {@code set&FactoryBean(...)}.
|
||||
*/
|
||||
@Test(expected=TypeMismatchException.class)
|
||||
@Test(expected = TypeMismatchException.class)
|
||||
public void testAutowireBeanWithFactoryBeanByName() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(LazyInitFactory.class);
|
||||
@@ -1664,8 +1683,8 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getMessage().indexOf("test") != -1);
|
||||
assertTrue(ex.getMessage().indexOf("spouse") != -1);
|
||||
assertTrue(ex.getMessage().contains("test"));
|
||||
assertTrue(ex.getMessage().contains("spouse"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1682,8 +1701,8 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getMessage().indexOf("test") != -1);
|
||||
assertTrue(ex.getMessage().indexOf("spouse") != -1);
|
||||
assertTrue(ex.getMessage().contains("test"));
|
||||
assertTrue(ex.getMessage().contains("spouse"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2518,7 +2537,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
assertEquals(expectedNameFromArgs, tb2.getName());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testScopingBeanToUnregisteredScopeResultsInAnException() throws Exception {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class);
|
||||
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
|
||||
<bean id="gamma" class="org.springframework.beans.factory.FactoryBeanTests$Gamma"/>
|
||||
|
||||
<bean id="betaFactory" class="org.springframework.beans.factory.FactoryBeanTests$BetaFactoryBean">
|
||||
<bean id="betaFactory" class="org.springframework.beans.factory.FactoryBeanTests$BetaFactoryBean" autowire="constructor">
|
||||
<property name="beta" ref="beta"/>
|
||||
</bean>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,7 +22,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
@@ -39,7 +38,7 @@ import static org.springframework.tests.TestResourceUtils.*;
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class FactoryBeanTests {
|
||||
public class FactoryBeanTests {
|
||||
|
||||
private static final Class<?> CLASS = FactoryBeanTests.class;
|
||||
private static final Resource RETURNS_NULL_CONTEXT = qualifiedResource(CLASS, "returnsNull.xml");
|
||||
@@ -47,6 +46,7 @@ public final class FactoryBeanTests {
|
||||
private static final Resource ABSTRACT_CONTEXT = qualifiedResource(CLASS, "abstract.xml");
|
||||
private static final Resource CIRCULAR_CONTEXT = qualifiedResource(CLASS, "circular.xml");
|
||||
|
||||
|
||||
@Test
|
||||
public void testFactoryBeanReturnsNull() throws Exception {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
@@ -63,10 +63,13 @@ public final class FactoryBeanTests {
|
||||
BeanFactoryPostProcessor ppc = (BeanFactoryPostProcessor) factory.getBean("propertyPlaceholderConfigurer");
|
||||
ppc.postProcessBeanFactory(factory);
|
||||
|
||||
assertNull(factory.getType("betaFactory"));
|
||||
|
||||
Alpha alpha = (Alpha) factory.getBean("alpha");
|
||||
Beta beta = (Beta) factory.getBean("beta");
|
||||
Gamma gamma = (Gamma) factory.getBean("gamma");
|
||||
Gamma gamma2 = (Gamma) factory.getBean("gammaFactory");
|
||||
|
||||
assertSame(beta, alpha.getBeta());
|
||||
assertSame(gamma, beta.getGamma());
|
||||
assertSame(gamma2, beta.getGamma());
|
||||
@@ -194,6 +197,9 @@ public final class FactoryBeanTests {
|
||||
@Component
|
||||
public static class BetaFactoryBean implements FactoryBean<Object> {
|
||||
|
||||
public BetaFactoryBean(Alpha alpha) {
|
||||
}
|
||||
|
||||
private Beta beta;
|
||||
|
||||
public void setBeta(Beta beta) {
|
||||
@@ -238,12 +244,12 @@ public final class FactoryBeanTests {
|
||||
public void setInstanceName(String instanceName) {
|
||||
this.instanceName = instanceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T getObject() {
|
||||
if (instance == null) {
|
||||
|
||||
+88
-127
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,6 @@ import java.util.prefs.BackingStoreException;
|
||||
import java.util.prefs.Preferences;
|
||||
import java.util.prefs.PreferencesFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
@@ -53,13 +52,13 @@ import static org.springframework.tests.TestResourceUtils.*;
|
||||
* {@link PropertyPlaceholderConfigurer}, {@link PropertyOverrideConfigurer} and
|
||||
* {@link PreferencesPlaceholderConfigurer}.
|
||||
*
|
||||
* @see PropertyPlaceholderConfigurerTests
|
||||
* @since 02.10.2003
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @author Phillip Webb
|
||||
* @since 02.10.2003
|
||||
* @see PropertyPlaceholderConfigurerTests
|
||||
*/
|
||||
public final class PropertyResourceConfigurerTests {
|
||||
public class PropertyResourceConfigurerTests {
|
||||
|
||||
static {
|
||||
System.setProperty("java.util.prefs.PreferencesFactory", MockPreferencesFactory.class.getName());
|
||||
@@ -70,23 +69,15 @@ public final class PropertyResourceConfigurerTests {
|
||||
private static final Resource XTEST_PROPS = qualifiedResource(CLASS, "xtest.properties"); // does not exist
|
||||
private static final Resource TEST_PROPS_XML = qualifiedResource(CLASS, "test.properties.xml");
|
||||
|
||||
private DefaultListableBeanFactory factory;
|
||||
private final DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
factory = new DefaultListableBeanFactory();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurer() {
|
||||
BeanDefinition def1 = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(TestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def1 = BeanDefinitionBuilder.genericBeanDefinition(TestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb1", def1);
|
||||
|
||||
BeanDefinition def2 = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(TestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def2 = BeanDefinitionBuilder.genericBeanDefinition(TestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb2", def2);
|
||||
|
||||
PropertyOverrideConfigurer poc1;
|
||||
@@ -123,9 +114,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithNestedProperty() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IndexedTestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(IndexedTestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb", def);
|
||||
|
||||
PropertyOverrideConfigurer poc;
|
||||
@@ -143,9 +132,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithNestedPropertyAndDotInBeanName() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IndexedTestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(IndexedTestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("my.tb", def);
|
||||
|
||||
PropertyOverrideConfigurer poc;
|
||||
@@ -164,9 +151,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithNestedMapPropertyAndDotInMapKey() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IndexedTestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(IndexedTestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb", def);
|
||||
|
||||
PropertyOverrideConfigurer poc;
|
||||
@@ -184,9 +169,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithHeldProperties() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(PropertiesHolder.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(PropertiesHolder.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb", def);
|
||||
|
||||
PropertyOverrideConfigurer poc;
|
||||
@@ -200,23 +183,9 @@ public final class PropertyResourceConfigurerTests {
|
||||
assertEquals("true", tb.getHeldProperties().getProperty("mail.smtp.auth"));
|
||||
}
|
||||
|
||||
static class PropertiesHolder {
|
||||
private Properties props = new Properties();
|
||||
|
||||
public Properties getHeldProperties() {
|
||||
return props;
|
||||
}
|
||||
|
||||
public void setHeldProperties(Properties props) {
|
||||
this.props = props;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithPropertiesFile() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IndexedTestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(IndexedTestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb", def);
|
||||
|
||||
PropertyOverrideConfigurer poc = new PropertyOverrideConfigurer();
|
||||
@@ -230,13 +199,11 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithInvalidPropertiesFile() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IndexedTestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(IndexedTestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb", def);
|
||||
|
||||
PropertyOverrideConfigurer poc = new PropertyOverrideConfigurer();
|
||||
poc.setLocations(new Resource[] { TEST_PROPS, XTEST_PROPS });
|
||||
poc.setLocations(TEST_PROPS, XTEST_PROPS);
|
||||
poc.setIgnoreResourceNotFound(true);
|
||||
poc.postProcessBeanFactory(factory);
|
||||
|
||||
@@ -247,9 +214,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithPropertiesXmlFile() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IndexedTestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(IndexedTestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb", def);
|
||||
|
||||
PropertyOverrideConfigurer poc = new PropertyOverrideConfigurer();
|
||||
@@ -263,9 +228,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithConvertProperties() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IndexedTestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(IndexedTestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb", def);
|
||||
|
||||
ConvertingOverrideConfigurer bfpp = new ConvertingOverrideConfigurer();
|
||||
@@ -389,7 +352,6 @@ public final class PropertyResourceConfigurerTests {
|
||||
cas.addGenericArgumentValue("${var}name${age}");
|
||||
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
|
||||
pvs.add("stringArray", new String[] {"${os.name}", "${age}"});
|
||||
|
||||
List<Object> friends = new ManagedList<Object>();
|
||||
@@ -409,7 +371,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
someMap.put("key1", new RuntimeBeanReference("${ref}"));
|
||||
someMap.put("key2", "${age}name");
|
||||
MutablePropertyValues innerPvs = new MutablePropertyValues();
|
||||
innerPvs.add("touchy", "${os.name}");
|
||||
innerPvs.add("country", "${os.name}");
|
||||
RootBeanDefinition innerBd = new RootBeanDefinition(TestBean.class);
|
||||
innerBd.setPropertyValues(innerPvs);
|
||||
someMap.put("key3", innerBd);
|
||||
@@ -459,30 +421,28 @@ public final class PropertyResourceConfigurerTests {
|
||||
TestBean inner2 = (TestBean) tb2.getSomeMap().get("mykey4");
|
||||
assertEquals(0, inner1.getAge());
|
||||
assertEquals(null, inner1.getName());
|
||||
assertEquals(System.getProperty("os.name"), inner1.getTouchy());
|
||||
assertEquals(System.getProperty("os.name"), inner1.getCountry());
|
||||
assertEquals(98, inner2.getAge());
|
||||
assertEquals("namemyvarmyvar${", inner2.getName());
|
||||
assertEquals(System.getProperty("os.name"), inner2.getTouchy());
|
||||
assertEquals(System.getProperty("os.name"), inner2.getCountry());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithSystemPropertyFallback() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${os.name}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("country", "${os.name}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.postProcessBeanFactory(factory);
|
||||
|
||||
TestBean tb = (TestBean) factory.getBean("tb");
|
||||
assertEquals(System.getProperty("os.name"), tb.getTouchy());
|
||||
assertEquals(System.getProperty("os.name"), tb.getCountry());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithSystemPropertyNotUsed() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${os.name}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("country", "${os.name}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -491,14 +451,13 @@ public final class PropertyResourceConfigurerTests {
|
||||
ppc.postProcessBeanFactory(factory);
|
||||
|
||||
TestBean tb = (TestBean) factory.getBean("tb");
|
||||
assertEquals("myos", tb.getTouchy());
|
||||
assertEquals("myos", tb.getCountry());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithOverridingSystemProperty() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${os.name}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("country", "${os.name}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -508,14 +467,13 @@ public final class PropertyResourceConfigurerTests {
|
||||
ppc.postProcessBeanFactory(factory);
|
||||
|
||||
TestBean tb = (TestBean) factory.getBean("tb");
|
||||
assertEquals(System.getProperty("os.name"), tb.getTouchy());
|
||||
assertEquals(System.getProperty("os.name"), tb.getCountry());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithUnresolvableSystemProperty() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${user.dir}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${user.dir}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_NEVER);
|
||||
@@ -532,9 +490,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithUnresolvablePlaceholder() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${ref}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${ref}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
|
||||
@@ -550,9 +507,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithIgnoreUnresolvablePlaceholder() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${ref}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${ref}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setIgnoreUnresolvablePlaceholders(true);
|
||||
@@ -564,9 +520,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithEmptyStringAsNull() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setNullValue("");
|
||||
@@ -578,9 +533,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithEmptyStringInPlaceholderAsNull() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${ref}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${ref}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setNullValue("");
|
||||
@@ -595,9 +549,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithNestedPlaceholderInKey() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${my${key}key}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${my${key}key}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -612,8 +565,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithPlaceholderInAlias() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class).getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class).getBeanDefinition());
|
||||
factory.registerAlias("tb", "${alias}");
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
@@ -629,8 +581,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithSelfReferencingPlaceholderInAlias() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class).getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class).getBeanDefinition());
|
||||
factory.registerAlias("tb", "${alias}");
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
@@ -646,11 +597,10 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithCircularReference() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("age", "${age}")
|
||||
.addPropertyValue("name", "name${var}")
|
||||
.getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("age", "${age}")
|
||||
.addPropertyValue("name", "name${var}")
|
||||
.getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -670,9 +620,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithDefaultProperties() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${test}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${test}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -686,9 +635,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithInlineDefault() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${test:mytest}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${test:mytest}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.postProcessBeanFactory(factory);
|
||||
@@ -699,9 +647,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithAliases() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${test}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${test}").getBeanDefinition());
|
||||
|
||||
factory.registerAlias("tb", "${myAlias}");
|
||||
factory.registerAlias("${myTarget}", "alias2");
|
||||
@@ -724,12 +671,11 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPreferencesPlaceholderConfigurer() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${myName}")
|
||||
.addPropertyValue("age", "${myAge}")
|
||||
.addPropertyValue("touchy", "${myTouchy}")
|
||||
.getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${myName}")
|
||||
.addPropertyValue("age", "${myAge}")
|
||||
.addPropertyValue("touchy", "${myTouchy}")
|
||||
.getBeanDefinition());
|
||||
|
||||
PreferencesPlaceholderConfigurer ppc = new PreferencesPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -752,12 +698,11 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPreferencesPlaceholderConfigurerWithCustomTreePaths() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${myName}")
|
||||
.addPropertyValue("age", "${myAge}")
|
||||
.addPropertyValue("touchy", "${myTouchy}")
|
||||
.getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${myName}")
|
||||
.addPropertyValue("age", "${myAge}")
|
||||
.addPropertyValue("touchy", "${myTouchy}")
|
||||
.getBeanDefinition());
|
||||
|
||||
PreferencesPlaceholderConfigurer ppc = new PreferencesPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -782,12 +727,11 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPreferencesPlaceholderConfigurerWithPathInPlaceholder() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${mypath/myName}")
|
||||
.addPropertyValue("age", "${myAge}")
|
||||
.addPropertyValue("touchy", "${myotherpath/myTouchy}")
|
||||
.getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${mypath/myName}")
|
||||
.addPropertyValue("age", "${myAge}")
|
||||
.addPropertyValue("touchy", "${myotherpath/myTouchy}")
|
||||
.getBeanDefinition());
|
||||
|
||||
PreferencesPlaceholderConfigurer ppc = new PreferencesPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -811,6 +755,20 @@ public final class PropertyResourceConfigurerTests {
|
||||
}
|
||||
|
||||
|
||||
static class PropertiesHolder {
|
||||
|
||||
private Properties props = new Properties();
|
||||
|
||||
public Properties getHeldProperties() {
|
||||
return props;
|
||||
}
|
||||
|
||||
public void setHeldProperties(Properties props) {
|
||||
this.props = props;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class ConvertingOverrideConfigurer extends PropertyOverrideConfigurer {
|
||||
|
||||
@Override
|
||||
@@ -819,26 +777,28 @@ public final class PropertyResourceConfigurerTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@link PreferencesFactory} to create {@link MockPreferences}.
|
||||
*/
|
||||
public static class MockPreferencesFactory implements PreferencesFactory {
|
||||
|
||||
private Preferences systemRoot = new MockPreferences();
|
||||
private final Preferences userRoot = new MockPreferences();
|
||||
|
||||
private Preferences userRoot = new MockPreferences();
|
||||
private final Preferences systemRoot = new MockPreferences();
|
||||
|
||||
@Override
|
||||
public Preferences systemRoot() {
|
||||
return systemRoot;
|
||||
return this.systemRoot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Preferences userRoot() {
|
||||
return userRoot;
|
||||
return this.userRoot;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mock implementation of {@link Preferences} that behaves the same regardless of the
|
||||
* underlying operating system and will never throw security exceptions.
|
||||
@@ -904,4 +864,5 @@ public final class PropertyResourceConfigurerTests {
|
||||
protected void flushSpi() throws BackingStoreException {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+27
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -770,7 +770,7 @@ public class BeanFactoryGenericsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpr11250() {
|
||||
public void testGenericMatchingWithBeanNameDifferentiation() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver());
|
||||
|
||||
@@ -780,8 +780,23 @@ public class BeanFactoryGenericsTests {
|
||||
new RootBeanDefinition(NumberBean.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR, false));
|
||||
|
||||
NumberBean nb = bf.getBean(NumberBean.class);
|
||||
assertNotNull(nb.getDoubleStore());
|
||||
assertNotNull(nb.getFloatStore());
|
||||
assertSame(bf.getBean("doubleStore"), nb.getDoubleStore());
|
||||
assertSame(bf.getBean("floatStore"), nb.getFloatStore());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericMatchingWithFullTypeDifferentiation() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver());
|
||||
|
||||
bf.registerBeanDefinition("store1", new RootBeanDefinition(DoubleStore.class));
|
||||
bf.registerBeanDefinition("store2", new RootBeanDefinition(FloatStore.class));
|
||||
bf.registerBeanDefinition("numberBean",
|
||||
new RootBeanDefinition(NumberBean.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR, false));
|
||||
|
||||
NumberBean nb = bf.getBean(NumberBean.class);
|
||||
assertSame(bf.getBean("store1"), nb.getDoubleStore());
|
||||
assertSame(bf.getBean("store2"), nb.getFloatStore());
|
||||
}
|
||||
|
||||
|
||||
@@ -851,6 +866,14 @@ public class BeanFactoryGenericsTests {
|
||||
}
|
||||
|
||||
|
||||
public static class DoubleStore extends NumberStore<Double> {
|
||||
}
|
||||
|
||||
|
||||
public static class FloatStore extends NumberStore<Float> {
|
||||
}
|
||||
|
||||
|
||||
public static class NumberBean {
|
||||
|
||||
private final NumberStore<Double> doubleStore;
|
||||
|
||||
+30
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -59,7 +59,6 @@ import static org.junit.Assert.*;
|
||||
* @author Rob Harrop
|
||||
* @author Arjen Poutsma
|
||||
* @author Chris Beams
|
||||
*
|
||||
* @since 10.06.2003
|
||||
*/
|
||||
public class CustomEditorTests {
|
||||
@@ -302,8 +301,8 @@ public class CustomEditorTests {
|
||||
|
||||
@Test
|
||||
public void testCustomBooleanEditorWithSpecialTrueAndFalseStrings() throws Exception {
|
||||
final String trueString = "pechorin";
|
||||
final String falseString = "nash";
|
||||
String trueString = "pechorin";
|
||||
String falseString = "nash";
|
||||
|
||||
CustomBooleanEditor editor = new CustomBooleanEditor(trueString, falseString, false);
|
||||
|
||||
@@ -320,6 +319,14 @@ public class CustomEditorTests {
|
||||
editor.setAsText(falseString.toUpperCase());
|
||||
assertFalse(((Boolean) editor.getValue()).booleanValue());
|
||||
assertEquals(falseString, editor.getAsText());
|
||||
|
||||
try {
|
||||
editor.setAsText(null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -423,7 +430,7 @@ public class CustomEditorTests {
|
||||
assertTrue("Correct bigDecimal value", new BigDecimal("4.5").equals(tb.getBigDecimal()));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCustomNumberEditorCtorWithNullNumberType() throws Exception {
|
||||
new CustomNumberEditor(null, true);
|
||||
}
|
||||
@@ -543,7 +550,7 @@ public class CustomEditorTests {
|
||||
assertNull(cb.getMyCharacter());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCharacterEditorSetAsTextWithStringLongerThanOneCharacter() throws Exception {
|
||||
PropertyEditor charEditor = new CharacterEditor(false);
|
||||
charEditor.setAsText("ColdWaterCanyon");
|
||||
@@ -562,7 +569,7 @@ public class CustomEditorTests {
|
||||
assertEquals(" ", charEditor.getAsText());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCharacterEditorSetAsTextWithNullNotAllowingEmptyAsNull() throws Exception {
|
||||
PropertyEditor charEditor = new CharacterEditor(false);
|
||||
charEditor.setAsText(null);
|
||||
@@ -583,7 +590,7 @@ public class CustomEditorTests {
|
||||
assertEquals("", classEditor.getAsText());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testClassEditorWithNonExistentClass() throws Exception {
|
||||
PropertyEditor classEditor = new ClassEditor();
|
||||
classEditor.setAsText("hairdresser.on.Fire");
|
||||
@@ -685,26 +692,40 @@ public class CustomEditorTests {
|
||||
@Test
|
||||
public void testCustomBooleanEditor() {
|
||||
CustomBooleanEditor editor = new CustomBooleanEditor(false);
|
||||
|
||||
editor.setAsText("true");
|
||||
assertEquals(Boolean.TRUE, editor.getValue());
|
||||
assertEquals("true", editor.getAsText());
|
||||
|
||||
editor.setAsText("false");
|
||||
assertEquals(Boolean.FALSE, editor.getValue());
|
||||
assertEquals("false", editor.getAsText());
|
||||
|
||||
editor.setValue(null);
|
||||
assertEquals(null, editor.getValue());
|
||||
assertEquals("", editor.getAsText());
|
||||
|
||||
try {
|
||||
editor.setAsText(null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomBooleanEditorWithEmptyAsNull() {
|
||||
CustomBooleanEditor editor = new CustomBooleanEditor(true);
|
||||
|
||||
editor.setAsText("true");
|
||||
assertEquals(Boolean.TRUE, editor.getValue());
|
||||
assertEquals("true", editor.getAsText());
|
||||
|
||||
editor.setAsText("false");
|
||||
assertEquals(Boolean.FALSE, editor.getValue());
|
||||
assertEquals("false", editor.getAsText());
|
||||
|
||||
editor.setValue(null);
|
||||
assertEquals(null, editor.getValue());
|
||||
assertEquals("", editor.getAsText());
|
||||
@@ -750,7 +771,7 @@ public class CustomEditorTests {
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getMessage().indexOf("10") != -1);
|
||||
assertTrue(ex.getMessage().contains("10"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,9 +30,9 @@ import static org.junit.Assert.*;
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class InputStreamEditorTests {
|
||||
public class InputStreamEditorTests {
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCtorWithNullResourceEditor() throws Exception {
|
||||
new InputStreamEditor(null);
|
||||
}
|
||||
@@ -41,7 +41,8 @@ public final class InputStreamEditorTests {
|
||||
public void testSunnyDay() throws Exception {
|
||||
InputStream stream = null;
|
||||
try {
|
||||
String resource = "classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass()) + ".class";
|
||||
String resource = "classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) +
|
||||
"/" + ClassUtils.getShortName(getClass()) + ".class";
|
||||
InputStreamEditor editor = new InputStreamEditor();
|
||||
editor.setAsText(resource);
|
||||
Object value = editor.getValue();
|
||||
@@ -49,14 +50,15 @@ public final class InputStreamEditorTests {
|
||||
assertTrue(value instanceof InputStream);
|
||||
stream = (InputStream) value;
|
||||
assertTrue(stream.available() > 0);
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
if (stream != null) {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWhenResourceDoesNotExist() throws Exception {
|
||||
String resource = "classpath:bingo!";
|
||||
InputStreamEditor editor = new InputStreamEditor();
|
||||
@@ -66,7 +68,8 @@ public final class InputStreamEditorTests {
|
||||
@Test
|
||||
public void testGetAsTextReturnsNullByDefault() throws Exception {
|
||||
assertNull(new InputStreamEditor().getAsText());
|
||||
String resource = "classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass()) + ".class";
|
||||
String resource = "classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) +
|
||||
"/" + ClassUtils.getShortName(getClass()) + ".class";
|
||||
InputStreamEditor editor = new InputStreamEditor();
|
||||
editor.setAsText(resource);
|
||||
assertNull(editor.getAsText());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
|
||||
+14
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,9 @@ import java.io.Serializable;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.support.SimpleValueWrapper;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -88,8 +91,16 @@ public class GuavaCache implements Cache {
|
||||
|
||||
@Override
|
||||
public ValueWrapper get(Object key) {
|
||||
Object value = this.cache.getIfPresent(key);
|
||||
return toWrapper(value);
|
||||
if (this.cache instanceof LoadingCache) {
|
||||
try {
|
||||
Object value = ((LoadingCache<Object, Object>) this.cache).get(key);
|
||||
return toWrapper(value);
|
||||
}
|
||||
catch (ExecutionException ex) {
|
||||
throw new UncheckedExecutionException(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
return toWrapper(this.cache.getIfPresent(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+7
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.cache.jcache.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.cache.annotation.AbstractCachingConfiguration;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.interceptor.CacheResolver;
|
||||
import org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource;
|
||||
import org.springframework.cache.jcache.interceptor.JCacheOperationSource;
|
||||
@@ -34,14 +35,16 @@ import org.springframework.context.annotation.Role;
|
||||
* @see JCacheConfigurer
|
||||
*/
|
||||
@Configuration
|
||||
public class AbstractJCacheConfiguration extends AbstractCachingConfiguration<JCacheConfigurer> {
|
||||
public class AbstractJCacheConfiguration extends AbstractCachingConfiguration {
|
||||
|
||||
protected CacheResolver exceptionCacheResolver;
|
||||
|
||||
@Override
|
||||
protected void useCachingConfigurer(JCacheConfigurer config) {
|
||||
protected void useCachingConfigurer(CachingConfigurer config) {
|
||||
super.useCachingConfigurer(config);
|
||||
this.exceptionCacheResolver = config.exceptionCacheResolver();
|
||||
if (config instanceof JCacheConfigurer) {
|
||||
this.exceptionCacheResolver = ((JCacheConfigurer) config).exceptionCacheResolver();
|
||||
}
|
||||
}
|
||||
|
||||
@Bean(name = "jCacheOperationSource")
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -128,9 +128,9 @@ public class DefaultJCacheOperationSource extends AnnotationJCacheOperationSourc
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
// Make sure those are initialized on startup...
|
||||
// Make sure that the cache resolver is initialized. An exception cache resolver is only
|
||||
// required if the exceptionCacheName attribute is set on an operation
|
||||
Assert.notNull(getDefaultCacheResolver(), "Cache resolver should have been initialized");
|
||||
Assert.notNull(getDefaultExceptionCacheResolver(), "Exception cache resolver should have been initialized");
|
||||
}
|
||||
|
||||
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,21 +28,21 @@ import org.springframework.cache.interceptor.CacheResolver;
|
||||
* <p>A cache operation can be statically cached as it does not contain
|
||||
* any runtime operation of a specific cache invocation.
|
||||
*
|
||||
* @param <A> the type of the JSR-107 annotation
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.1
|
||||
* @param <A> the type of the JSR-107 annotation
|
||||
*/
|
||||
public interface JCacheOperation<A extends Annotation> extends BasicOperation, CacheMethodDetails<A> {
|
||||
|
||||
/**
|
||||
* Return the {@link CacheResolver} instance to use to resolve the cache to
|
||||
* use for this operation.
|
||||
* Return the {@link CacheResolver} instance to use to resolve the cache
|
||||
* to use for this operation.
|
||||
*/
|
||||
CacheResolver getCacheResolver();
|
||||
|
||||
/**
|
||||
* Return the {@link CacheInvocationParameter} instances based on the specified
|
||||
* method arguments.
|
||||
* Return the {@link CacheInvocationParameter} instances based on the
|
||||
* specified method arguments.
|
||||
* <p>The method arguments must match the signature of the related method invocation
|
||||
* @param values the parameters value for a particular invocation
|
||||
*/
|
||||
|
||||
Vendored
+29
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,10 @@ package org.springframework.cache.guava;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
@@ -32,6 +35,9 @@ import static org.mockito.Mockito.*;
|
||||
*/
|
||||
public class GuavaCacheManagerTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void testDynamicMode() {
|
||||
CacheManager cm = new GuavaCacheManager();
|
||||
@@ -150,6 +156,28 @@ public class GuavaCacheManagerTests {
|
||||
assertNotNull(cm.getCache("someCache"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheLoaderUseLoadingCache() {
|
||||
GuavaCacheManager cm = new GuavaCacheManager("c1");
|
||||
cm.setCacheLoader(new CacheLoader<Object, Object>() {
|
||||
@Override
|
||||
public Object load(Object key) throws Exception {
|
||||
if ("ping".equals(key)) {
|
||||
return "pong";
|
||||
}
|
||||
throw new IllegalArgumentException("I only know ping");
|
||||
}
|
||||
});
|
||||
Cache cache1 = cm.getCache("c1");
|
||||
Cache.ValueWrapper value = cache1.get("ping");
|
||||
assertNotNull(value);
|
||||
assertEquals("pong", value.get());
|
||||
|
||||
thrown.expect(UncheckedExecutionException.class);
|
||||
thrown.expectMessage("I only know ping");
|
||||
assertNull(cache1.get("foo"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private CacheLoader<Object, Object> mockCacheLoader() {
|
||||
return mock(CacheLoader.class);
|
||||
|
||||
+46
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,12 +18,15 @@ package org.springframework.cache.jcache.config;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||
import org.springframework.cache.config.SomeKeyGenerator;
|
||||
import org.springframework.cache.interceptor.CacheErrorHandler;
|
||||
import org.springframework.cache.interceptor.CacheResolver;
|
||||
@@ -35,7 +38,6 @@ import org.springframework.cache.interceptor.SimpleKeyGenerator;
|
||||
import org.springframework.cache.jcache.interceptor.AnnotatedJCacheableService;
|
||||
import org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource;
|
||||
import org.springframework.cache.jcache.interceptor.JCacheInterceptor;
|
||||
import org.springframework.cache.jcache.interceptor.SimpleExceptionCacheResolver;
|
||||
import org.springframework.cache.support.NoOpCacheManager;
|
||||
import org.springframework.cache.support.SimpleCacheManager;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -51,6 +53,9 @@ import static org.junit.Assert.*;
|
||||
*/
|
||||
public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Override
|
||||
protected ApplicationContext getApplicationContext() {
|
||||
return new AnnotationConfigApplicationContext(EnableCachingConfig.class);
|
||||
@@ -80,10 +85,7 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||
assertEquals(SimpleCacheResolver.class, cos.getCacheResolver().getClass());
|
||||
assertSame(context.getBean(CacheManager.class),
|
||||
((SimpleCacheResolver) cos.getCacheResolver()).getCacheManager());
|
||||
assertNotNull(cos.getExceptionCacheResolver());
|
||||
assertEquals(SimpleExceptionCacheResolver.class, cos.getExceptionCacheResolver().getClass());
|
||||
assertSame(context.getBean(CacheManager.class),
|
||||
((SimpleExceptionCacheResolver) cos.getExceptionCacheResolver()).getCacheManager());
|
||||
assertNull(cos.getExceptionCacheResolver());
|
||||
context.close();
|
||||
}
|
||||
|
||||
@@ -99,6 +101,28 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exceptionCacheResolverFallbacksToMainOne() {
|
||||
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
NoExceptionCacheResolverConfig.class);
|
||||
try {
|
||||
DefaultJCacheOperationSource cos = context.getBean(DefaultJCacheOperationSource.class);
|
||||
assertSame(context.getBean("cacheResolver"), cos.getCacheResolver());
|
||||
assertNull(cos.getExceptionCacheResolver());
|
||||
|
||||
JCacheableService<?> service = context.getBean(JCacheableService.class);
|
||||
|
||||
service.cache("id");
|
||||
|
||||
// This call requires the cache manager to be set
|
||||
thrown.expect(IllegalStateException.class);
|
||||
service.cacheWithException("test", false);
|
||||
}
|
||||
finally {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
@@ -200,4 +224,20 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class NoExceptionCacheResolverConfig extends JCacheConfigurerSupport {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public CacheResolver cacheResolver() {
|
||||
return new NamedCacheResolver(new ConcurrentMapCacheManager(), "default");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JCacheableService<?> cacheableService() {
|
||||
return new AnnotatedJCacheableService(new ConcurrentMapCache("default"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-2
@@ -381,17 +381,20 @@ public class QuartzSupportTests {
|
||||
|
||||
/**
|
||||
* SPR-6038: detect HSQL and stop illegal locks being taken.
|
||||
* TODO: Against Quartz 2.2, this test's job doesn't actually execute anymore...
|
||||
*/
|
||||
@Test
|
||||
public void schedulerWithHsqlDataSource() throws Exception {
|
||||
Assume.group(TestGroup.PERFORMANCE);
|
||||
// Assume.group(TestGroup.PERFORMANCE);
|
||||
|
||||
DummyJob.param = 0;
|
||||
DummyJob.count = 0;
|
||||
|
||||
ClassPathXmlApplicationContext ctx = context("databasePersistence.xml");
|
||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(ctx.getBean(DataSource.class));
|
||||
assertTrue("No triggers were persisted", jdbcTemplate.queryForList("SELECT * FROM qrtz_triggers").size()>0);
|
||||
assertFalse("No triggers were persisted", jdbcTemplate.queryForList("SELECT * FROM qrtz_triggers").isEmpty());
|
||||
|
||||
/*
|
||||
Thread.sleep(3000);
|
||||
try {
|
||||
assertTrue(DummyJob.count > 0);
|
||||
@@ -399,6 +402,7 @@ public class QuartzSupportTests {
|
||||
finally {
|
||||
ctx.close();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private ClassPathXmlApplicationContext context(String path) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,7 @@
|
||||
package org.springframework.cache;
|
||||
|
||||
/**
|
||||
* Interface that defines the common cache operations.
|
||||
* Interface that defines common cache operations.
|
||||
*
|
||||
* <b>Note:</b> Due to the generic use of caching, it is recommended that
|
||||
* implementations allow storage of <tt>null</tt> values (for example to
|
||||
@@ -68,8 +68,8 @@ public interface Cache {
|
||||
* the cache contains no mapping for this key
|
||||
* @throws IllegalStateException if a cache entry has been found
|
||||
* but failed to match the specified type
|
||||
* @see #get(Object)
|
||||
* @since 4.0
|
||||
* @see #get(Object)
|
||||
*/
|
||||
<T> T get(Object key, Class<T> type);
|
||||
|
||||
|
||||
Vendored
+12
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.cache.annotation;
|
||||
|
||||
import java.util.Collection;
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.CacheManager;
|
||||
@@ -28,12 +27,11 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Abstract base {@code @Configuration} class providing common structure for enabling
|
||||
* Spring's annotation-driven cache management capability.
|
||||
* Abstract base {@code @Configuration} class providing common structure
|
||||
* for enabling Spring's annotation-driven cache management capability.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Stephane Nicoll
|
||||
@@ -41,7 +39,7 @@ import org.springframework.util.CollectionUtils;
|
||||
* @see EnableCaching
|
||||
*/
|
||||
@Configuration
|
||||
public abstract class AbstractCachingConfiguration<C extends CachingConfigurer> implements ImportAware {
|
||||
public abstract class AbstractCachingConfiguration implements ImportAware {
|
||||
|
||||
protected AnnotationAttributes enableCaching;
|
||||
|
||||
@@ -53,17 +51,19 @@ public abstract class AbstractCachingConfiguration<C extends CachingConfigurer>
|
||||
|
||||
protected CacheErrorHandler errorHandler;
|
||||
|
||||
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
this.enableCaching = AnnotationAttributes.fromMap(
|
||||
importMetadata.getAnnotationAttributes(EnableCaching.class.getName(), false));
|
||||
Assert.notNull(this.enableCaching,
|
||||
"@EnableCaching is not present on importing class " +
|
||||
importMetadata.getClassName());
|
||||
if (this.enableCaching == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"@EnableCaching is not present on importing class " + importMetadata.getClassName());
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
void setConfigurers(Collection<C> configurers) {
|
||||
void setConfigurers(Collection<CachingConfigurer> configurers) {
|
||||
if (CollectionUtils.isEmpty(configurers)) {
|
||||
return;
|
||||
}
|
||||
@@ -73,14 +73,14 @@ public abstract class AbstractCachingConfiguration<C extends CachingConfigurer>
|
||||
"Refactor the configuration such that CachingConfigurer is " +
|
||||
"implemented only once or not at all.");
|
||||
}
|
||||
C configurer = configurers.iterator().next();
|
||||
CachingConfigurer configurer = configurers.iterator().next();
|
||||
useCachingConfigurer(configurer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the configuration from the nominated {@link CachingConfigurer}.
|
||||
*/
|
||||
protected void useCachingConfigurer(C config) {
|
||||
protected void useCachingConfigurer(CachingConfigurer config) {
|
||||
this.cacheManager = config.cacheManager();
|
||||
this.cacheResolver = config.cacheResolver();
|
||||
this.keyGenerator = config.keyGenerator();
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -162,13 +162,12 @@ public @interface EnableCaching {
|
||||
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
|
||||
* to standard Java interface-based proxies. The default is {@code false}. <strong>
|
||||
* Applicable only if {@link #mode()} is set to {@link AdviceMode#PROXY}</strong>.
|
||||
*
|
||||
* <p>Note that setting this attribute to {@code true} will affect <em>all</em>
|
||||
* Spring-managed beans requiring proxying, not just those marked with
|
||||
* {@code @Cacheable}. For example, other beans marked with Spring's
|
||||
* {@code @Transactional} annotation will be upgraded to subclass proxying at the same
|
||||
* time. This approach has no negative impact in practice unless one is explicitly
|
||||
* expecting one type of proxy vs another, e.g. in tests.
|
||||
* Spring-managed beans requiring proxying, not just those marked with {@code @Cacheable}.
|
||||
* For example, other beans marked with Spring's {@code @Transactional} annotation will
|
||||
* be upgraded to subclass proxying at the same time. This approach has no negative
|
||||
* impact in practice unless one is explicitly expecting one type of proxy vs another,
|
||||
* e.g. in tests.
|
||||
*/
|
||||
boolean proxyTargetClass() default false;
|
||||
|
||||
@@ -185,4 +184,5 @@ public @interface EnableCaching {
|
||||
* The default is {@link Ordered#LOWEST_PRECEDENCE}.
|
||||
*/
|
||||
int order() default Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,7 +35,7 @@ import org.springframework.context.annotation.Role;
|
||||
* @see CachingConfigurationSelector
|
||||
*/
|
||||
@Configuration
|
||||
public class ProxyCachingConfiguration extends AbstractCachingConfiguration<CachingConfigurer> {
|
||||
public class ProxyCachingConfiguration extends AbstractCachingConfiguration {
|
||||
|
||||
@Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
|
||||
Vendored
+1
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -235,11 +235,6 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria
|
||||
"default cache resolver if none is set. If a cache resolver is set, the cache manager" +
|
||||
"won't be used.");
|
||||
}
|
||||
if (operation.getCacheNames().isEmpty()) {
|
||||
throw new IllegalStateException("No cache names could be detected on '" +
|
||||
ae.toString() + "'. Make sure to set the value parameter on the annotation or " +
|
||||
"declare a @CacheConfig at the class-level with the default cache name(s) to use.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,7 +23,7 @@ import org.springframework.cache.Cache;
|
||||
/**
|
||||
* Determine the {@link Cache} instance(s) to use for an intercepted method invocation.
|
||||
*
|
||||
* <p>Implementations MUST be thread-safe.
|
||||
* <p>Implementations must be thread-safe.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.1
|
||||
@@ -32,9 +32,8 @@ public interface CacheResolver {
|
||||
|
||||
/**
|
||||
* Return the cache(s) to use for the specified invocation.
|
||||
*
|
||||
* @param context the context of the particular invocation
|
||||
* @return the cache(s) to use (never null)
|
||||
* @return the cache(s) to use (never {@code null})
|
||||
*/
|
||||
Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,13 +17,15 @@
|
||||
package org.springframework.context;
|
||||
|
||||
/**
|
||||
* Interface defining methods for start/stop lifecycle control.
|
||||
* A common interface defining methods for start/stop lifecycle control.
|
||||
* The typical use case for this is to control asynchronous processing.
|
||||
* <b>NOTE: This interface does not imply specific auto-startup semantics.
|
||||
* Consider implementing {@link SmartLifecycle} for that purpose.</b>
|
||||
*
|
||||
* <p>Can be implemented by both components (typically a Spring bean defined in
|
||||
* a Spring {@link org.springframework.beans.factory.BeanFactory}) and containers
|
||||
* (typically a Spring {@link ApplicationContext}). Containers will propagate
|
||||
* start/stop signals to all components that apply.
|
||||
* <p>Can be implemented by both components (typically a Spring bean defined in a
|
||||
* Spring context) and containers (typically a Spring {@link ApplicationContext}
|
||||
* itself). Containers will propagate start/stop signals to all components that
|
||||
* apply within each container, e.g. for a stop/restart scenario at runtime.
|
||||
*
|
||||
* <p>Can be used for direct invocations or for management operations via JMX.
|
||||
* In the latter case, the {@link org.springframework.jmx.export.MBeanExporter}
|
||||
@@ -32,10 +34,10 @@ package org.springframework.context;
|
||||
* restricting the visibility of activity-controlled components to the Lifecycle
|
||||
* interface.
|
||||
*
|
||||
* <p>Note that the Lifecycle interface is only supported on <b>top-level singleton beans</b>.
|
||||
* On any other component, the Lifecycle interface will remain undetected and hence ignored.
|
||||
* Also, note that the extended {@link SmartLifecycle} interface provides more sophisticated
|
||||
* integration with the container's startup and shutdown phases.
|
||||
* <p>Note that the Lifecycle interface is only supported on <b>top-level singleton
|
||||
* beans</b>. On any other component, the Lifecycle interface will remain undetected
|
||||
* and hence ignored. Also, note that the extended {@link SmartLifecycle} interface
|
||||
* provides integration with the application context's startup and shutdown phases.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
@@ -51,6 +53,7 @@ public interface Lifecycle {
|
||||
* Should not throw an exception if the component is already running.
|
||||
* <p>In the case of a container, this will propagate the start signal
|
||||
* to all components that apply.
|
||||
* @see SmartLifecycle#isAutoStartup()
|
||||
*/
|
||||
void start();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,8 +17,8 @@
|
||||
package org.springframework.context;
|
||||
|
||||
/**
|
||||
* An extension of the {@link Lifecycle} interface for those objects that require to be
|
||||
* started upon ApplicationContext refresh and/or shutdown in a particular order.
|
||||
* An extension of the {@link Lifecycle} interface for those objects that require to
|
||||
* be started upon ApplicationContext refresh and/or shutdown in a particular order.
|
||||
* The {@link #isAutoStartup()} return value indicates whether this object should
|
||||
* be started at the time of a context refresh. The callback-accepting
|
||||
* {@link #stop(Runnable)} method is useful for objects that have an asynchronous
|
||||
@@ -55,26 +55,37 @@ package org.springframework.context;
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 3.0
|
||||
* @see LifecycleProcessor
|
||||
* @see ConfigurableApplicationContext
|
||||
*/
|
||||
public interface SmartLifecycle extends Lifecycle, Phased {
|
||||
|
||||
/**
|
||||
* Return whether this Lifecycle component should be started automatically
|
||||
* by the container when the ApplicationContext is refreshed. A value of
|
||||
* "false" indicates that the component is intended to be started manually.
|
||||
* Returns {@code true} if this {@code Lifecycle} component should get
|
||||
* started automatically by the container at the time that the containing
|
||||
* {@link ApplicationContext} gets refreshed.
|
||||
* <p>A value of {@code false} indicates that the component is intended to
|
||||
* be started through an explicit {@link #start()} call instead, analogous
|
||||
* to a plain {@link Lifecycle} implementation.
|
||||
* @see #start()
|
||||
* @see #getPhase()
|
||||
* @see LifecycleProcessor#onRefresh()
|
||||
* @see ConfigurableApplicationContext#refresh()
|
||||
*/
|
||||
boolean isAutoStartup();
|
||||
|
||||
/**
|
||||
* Indicates that a Lifecycle component must stop if it is currently running.
|
||||
* <p>The provided callback is used by the {@link LifecycleProcessor} to support an
|
||||
* ordered, and potentially concurrent, shutdown of all components having a
|
||||
* <p>The provided callback is used by the {@link LifecycleProcessor} to support
|
||||
* an ordered, and potentially concurrent, shutdown of all components having a
|
||||
* common shutdown order value. The callback <b>must</b> be executed after
|
||||
* the SmartLifecycle component does indeed stop.
|
||||
* <p>The {@code LifecycleProcessor} will call <i>only</i> this variant of the
|
||||
* the {@code SmartLifecycle} component does indeed stop.
|
||||
* <p>The {@link LifecycleProcessor} will call <i>only</i> this variant of the
|
||||
* {@code stop} method; i.e. {@link Lifecycle#stop()} will not be called for
|
||||
* {@link SmartLifecycle} implementations unless explicitly delegated to within
|
||||
* this method.
|
||||
* {@code SmartLifecycle} implementations unless explicitly delegated to within
|
||||
* the implementation of this method.
|
||||
* @see #stop()
|
||||
* @see #getPhase()
|
||||
*/
|
||||
void stop(Runnable callback);
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,9 +28,9 @@ import org.springframework.util.Assert;
|
||||
* based on an {@link AdviceMode} value from an annotation (such as the {@code @Enable*}
|
||||
* annotations).
|
||||
*
|
||||
* @param <A> Annotation containing {@linkplain #getAdviceModeAttributeName() AdviceMode attribute}
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
* @param <A> annotation containing {@linkplain #getAdviceModeAttributeName() AdviceMode attribute}
|
||||
*/
|
||||
public abstract class AdviceModeImportSelector<A extends Annotation> implements ImportSelector {
|
||||
|
||||
|
||||
+4
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
@@ -63,6 +64,8 @@ final class ConfigurationClass {
|
||||
private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars =
|
||||
new LinkedHashMap<ImportBeanDefinitionRegistrar, AnnotationMetadata>();
|
||||
|
||||
final Set<String> skippedBeanMethods = new HashSet<String>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigurationClass} with the given name.
|
||||
|
||||
+29
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -168,7 +168,7 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
|
||||
configClass.setBeanName(configBeanName);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Registered bean definition for imported @Configuration class %s", configBeanName));
|
||||
logger.debug("Registered bean definition for imported class '" + configBeanName + "'");
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -182,33 +182,25 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
* with the BeanDefinitionRegistry based on its contents.
|
||||
*/
|
||||
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
|
||||
if (this.conditionEvaluator.shouldSkip(beanMethod.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigurationClass configClass = beanMethod.getConfigurationClass();
|
||||
MethodMetadata metadata = beanMethod.getMetadata();
|
||||
String methodName = metadata.getMethodName();
|
||||
|
||||
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
|
||||
beanDef.setResource(configClass.getResource());
|
||||
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
|
||||
if (metadata.isStatic()) {
|
||||
// static @Bean method
|
||||
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
|
||||
beanDef.setFactoryMethodName(metadata.getMethodName());
|
||||
// Do we need to mark the bean as skipped by its condition?
|
||||
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
|
||||
configClass.skippedBeanMethods.add(methodName);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// instance @Bean method
|
||||
beanDef.setFactoryBeanName(configClass.getBeanName());
|
||||
beanDef.setUniqueFactoryMethodName(metadata.getMethodName());
|
||||
if (configClass.skippedBeanMethods.contains(methodName)) {
|
||||
return;
|
||||
}
|
||||
beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
|
||||
beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
|
||||
|
||||
// Consider name and any aliases
|
||||
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
|
||||
List<String> names = new ArrayList<String>(Arrays.asList(bean.getStringArray("name")));
|
||||
String beanName = (names.size() > 0 ? names.remove(0) : beanMethod.getMetadata().getMethodName());
|
||||
String beanName = (names.size() > 0 ? names.remove(0) : methodName);
|
||||
|
||||
// Register aliases even when overridden
|
||||
for (String alias : names) {
|
||||
this.registry.registerAlias(beanName, alias);
|
||||
}
|
||||
@@ -218,6 +210,23 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
|
||||
beanDef.setResource(configClass.getResource());
|
||||
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
|
||||
|
||||
if (metadata.isStatic()) {
|
||||
// static @Bean method
|
||||
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
|
||||
beanDef.setFactoryMethodName(methodName);
|
||||
}
|
||||
else {
|
||||
// instance @Bean method
|
||||
beanDef.setFactoryBeanName(configClass.getBeanName());
|
||||
beanDef.setUniqueFactoryMethodName(methodName);
|
||||
}
|
||||
beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
|
||||
beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
|
||||
|
||||
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
|
||||
|
||||
Autowire autowire = bean.getEnum("autowire");
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -303,7 +303,7 @@ class ConfigurationClassEnhancer {
|
||||
"result in a failure to process annotations such as @Autowired, " +
|
||||
"@Resource and @PostConstruct within the method's declaring " +
|
||||
"@Configuration class. Add the 'static' modifier to this method to avoid " +
|
||||
"these container lifecycle issues; see @Bean javadoc for complete details",
|
||||
"these container lifecycle issues; see @Bean javadoc for complete details.",
|
||||
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
|
||||
}
|
||||
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
|
||||
|
||||
+35
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -73,6 +73,7 @@ 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.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -133,7 +134,7 @@ class ConfigurationClassParser {
|
||||
|
||||
private final ImportStack importStack = new ImportStack();
|
||||
|
||||
private final List<DeferredImportSelectorHolder> deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
|
||||
private List<DeferredImportSelectorHolder> deferredImportSelectors;
|
||||
|
||||
|
||||
/**
|
||||
@@ -156,6 +157,8 @@ class ConfigurationClassParser {
|
||||
|
||||
|
||||
public void parse(Set<BeanDefinitionHolder> configCandidates) {
|
||||
this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
|
||||
|
||||
for (BeanDefinitionHolder holder : configCandidates) {
|
||||
BeanDefinition bd = holder.getBeanDefinition();
|
||||
try {
|
||||
@@ -177,6 +180,7 @@ class ConfigurationClassParser {
|
||||
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
processDeferredImportSelectors();
|
||||
}
|
||||
|
||||
@@ -269,7 +273,7 @@ class ConfigurationClassParser {
|
||||
}
|
||||
|
||||
// Process any @Import annotations
|
||||
processImports(configClass, sourceClass, getImports(sourceClass), true, false);
|
||||
processImports(configClass, sourceClass, getImports(sourceClass), true);
|
||||
|
||||
// Process any @ImportResource annotations
|
||||
if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
|
||||
@@ -416,12 +420,15 @@ class ConfigurationClassParser {
|
||||
}
|
||||
|
||||
private void processDeferredImportSelectors() {
|
||||
Collections.sort(this.deferredImportSelectors, DEFERRED_IMPORT_COMPARATOR);
|
||||
for (DeferredImportSelectorHolder deferredImport : this.deferredImportSelectors) {
|
||||
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
|
||||
this.deferredImportSelectors = null;
|
||||
Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR);
|
||||
|
||||
for (DeferredImportSelectorHolder deferredImport : deferredImports) {
|
||||
ConfigurationClass configClass = deferredImport.getConfigurationClass();
|
||||
try {
|
||||
String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());
|
||||
processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false, true);
|
||||
processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false);
|
||||
}
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
throw ex;
|
||||
@@ -431,18 +438,17 @@ class ConfigurationClassParser {
|
||||
configClass.getMetadata().getClassName() + "]", ex);
|
||||
}
|
||||
}
|
||||
this.deferredImportSelectors.clear();
|
||||
}
|
||||
|
||||
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
|
||||
Collection<SourceClass> importCandidates, boolean checkForCircularImports, boolean deferred) throws IOException {
|
||||
Collection<SourceClass> importCandidates, boolean checkForCircularImports) throws IOException {
|
||||
|
||||
if (importCandidates.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkForCircularImports && this.importStack.contains(configClass)) {
|
||||
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack, configClass.getMetadata()));
|
||||
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
|
||||
}
|
||||
else {
|
||||
this.importStack.push(configClass);
|
||||
@@ -453,14 +459,14 @@ class ConfigurationClassParser {
|
||||
Class<?> candidateClass = candidate.loadClass();
|
||||
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
|
||||
invokeAwareMethods(selector);
|
||||
if (!deferred && selector instanceof DeferredImportSelector) {
|
||||
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
|
||||
this.deferredImportSelectors.add(
|
||||
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
|
||||
}
|
||||
else {
|
||||
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
|
||||
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
|
||||
processImports(configClass, currentSourceClass, importSourceClasses, false, false);
|
||||
processImports(configClass, currentSourceClass, importSourceClasses, false);
|
||||
}
|
||||
}
|
||||
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
|
||||
@@ -474,7 +480,7 @@ class ConfigurationClassParser {
|
||||
}
|
||||
else {
|
||||
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
|
||||
// process it as a @Configuration class
|
||||
// process it as an @Configuration class
|
||||
this.importStack.registerImport(
|
||||
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
|
||||
processConfigurationClass(candidate.asConfigClass(configClass));
|
||||
@@ -615,7 +621,7 @@ class ConfigurationClassParser {
|
||||
@Override
|
||||
public AnnotationMetadata getImportingClassFor(String importedClass) {
|
||||
List<AnnotationMetadata> list = this.imports.get(importedClass);
|
||||
return (list == null || list.isEmpty() ? null : list.get(list.size() - 1));
|
||||
return (!CollectionUtils.isEmpty(list) ? list.get(list.size() - 1) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -629,7 +635,7 @@ class ConfigurationClassParser {
|
||||
Comparator<ConfigurationClass> comparator = new Comparator<ConfigurationClass>() {
|
||||
@Override
|
||||
public int compare(ConfigurationClass first, ConfigurationClass second) {
|
||||
return first.getMetadata().getClassName().equals(second.getMetadata().getClassName()) ? 0 : 1;
|
||||
return (first.getMetadata().getClassName().equals(second.getMetadata().getClassName()) ? 0 : 1);
|
||||
}
|
||||
};
|
||||
return (Collections.binarySearch(this, configClass, comparator) != -1);
|
||||
@@ -642,11 +648,11 @@ class ConfigurationClassParser {
|
||||
* <li>com.acme.Bar</li>
|
||||
* <li>com.acme.Baz</li>
|
||||
* </ul>
|
||||
* return "ImportStack: [Foo->Bar->Baz]".
|
||||
* return "[Foo->Bar->Baz]".
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder("ImportStack: [");
|
||||
StringBuilder builder = new StringBuilder("[");
|
||||
Iterator<ConfigurationClass> iterator = iterator();
|
||||
while (iterator.hasNext()) {
|
||||
builder.append(iterator.next().getSimpleName());
|
||||
@@ -750,7 +756,16 @@ class ConfigurationClassParser {
|
||||
String[] memberClassNames = sourceReader.getClassMetadata().getMemberClassNames();
|
||||
List<SourceClass> members = new ArrayList<SourceClass>(memberClassNames.length);
|
||||
for (String memberClassName : memberClassNames) {
|
||||
members.add(asSourceClass(memberClassName));
|
||||
try {
|
||||
members.add(asSourceClass(memberClassName));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// Let's skip it if it's not resolvable - we're just looking for candidates
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to resolve member class [" + memberClassName +
|
||||
"] - not considering it as a configuration class candidate");
|
||||
}
|
||||
}
|
||||
}
|
||||
return members;
|
||||
}
|
||||
@@ -829,12 +844,12 @@ class ConfigurationClassParser {
|
||||
*/
|
||||
private static class CircularImportProblem extends Problem {
|
||||
|
||||
public CircularImportProblem(ConfigurationClass attemptedImport, Stack<ConfigurationClass> importStack, AnnotationMetadata metadata) {
|
||||
public CircularImportProblem(ConfigurationClass attemptedImport, Stack<ConfigurationClass> importStack) {
|
||||
super(String.format("A circular @Import has been detected: " +
|
||||
"Illegal attempt by @Configuration class '%s' to import class '%s' as '%s' is " +
|
||||
"already present in the current import stack [%s]", importStack.peek().getSimpleName(),
|
||||
"already present in the current import stack %s", importStack.peek().getSimpleName(),
|
||||
attemptedImport.getSimpleName(), attemptedImport.getSimpleName(), importStack),
|
||||
new Location(importStack.peek().getResource(), metadata));
|
||||
new Location(importStack.peek().getResource(), attemptedImport.getMetadata()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -149,12 +149,24 @@ abstract class ConfigurationClassUtils {
|
||||
if (metadata.isInterface()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Any of the typical annotations found?
|
||||
for (String indicator : candidateIndicators) {
|
||||
if (metadata.isAnnotated(indicator)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return metadata.hasAnnotatedMethods(Bean.class.getName());
|
||||
|
||||
// Finally, let's look for @Bean methods...
|
||||
try {
|
||||
return metadata.hasAnnotatedMethods(Bean.class.getName());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClass() + "]: " + ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,16 +30,16 @@ import java.lang.annotation.Target;
|
||||
* one {@link Bean @Bean} method, as well as {@link ImportSelector} and
|
||||
* {@link ImportBeanDefinitionRegistrar} implementations.
|
||||
*
|
||||
* <p>{@code @Bean} definitions declared in imported {@code @Configuration} classes
|
||||
* should be accessed by using {@link org.springframework.beans.factory.annotation.Autowired @Autowired}
|
||||
* <p>{@code @Bean} definitions declared in imported {@code @Configuration} classes should be
|
||||
* accessed by using {@link org.springframework.beans.factory.annotation.Autowired @Autowired}
|
||||
* injection. Either the bean itself can be autowired, or the configuration class instance
|
||||
* declaring the bean can be autowired. The latter approach allows for explicit,
|
||||
* IDE-friendly navigation between {@code @Configuration} class methods.
|
||||
* declaring the bean can be autowired. The latter approach allows for explicit, IDE-friendly
|
||||
* navigation between {@code @Configuration} class methods.
|
||||
*
|
||||
* <p>May be declared at the class level or as a meta-annotation.
|
||||
*
|
||||
* <p>If XML or other non-{@code @Configuration} bean definition resources need to be
|
||||
* imported, use {@link ImportResource @ImportResource}
|
||||
* imported, use the {@link ImportResource @ImportResource} annotation instead.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.0
|
||||
@@ -57,4 +57,5 @@ public @interface Import {
|
||||
* {@link ImportBeanDefinitionRegistrar} classes to import.
|
||||
*/
|
||||
Class<?>[] value();
|
||||
|
||||
}
|
||||
|
||||
+12
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,9 +26,6 @@ import org.springframework.context.weaving.DefaultContextLoadTimeWeaver;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.instrument.classloading.LoadTimeWeaver;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import static org.springframework.context.weaving.AspectJWeavingEnabler.*;
|
||||
|
||||
/**
|
||||
* {@code @Configuration} class that registers a {@link LoadTimeWeaver} bean.
|
||||
@@ -47,7 +44,6 @@ public class LoadTimeWeavingConfiguration implements ImportAware, BeanClassLoade
|
||||
|
||||
private AnnotationAttributes enableLTW;
|
||||
|
||||
@Autowired(required=false)
|
||||
private LoadTimeWeavingConfigurer ltwConfigurer;
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
@@ -56,8 +52,15 @@ public class LoadTimeWeavingConfiguration implements ImportAware, BeanClassLoade
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
this.enableLTW = AnnotationConfigUtils.attributesFor(importMetadata, EnableLoadTimeWeaving.class);
|
||||
Assert.notNull(this.enableLTW,
|
||||
"@EnableLoadTimeWeaving is not present on importing class " + importMetadata.getClassName());
|
||||
if (this.enableLTW == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"@EnableLoadTimeWeaving is not present on importing class " + importMetadata.getClassName());
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setLoadTimeWeavingConfigurer(LoadTimeWeavingConfigurer ltwConfigurer) {
|
||||
this.ltwConfigurer = ltwConfigurer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,7 +69,7 @@ public class LoadTimeWeavingConfiguration implements ImportAware, BeanClassLoade
|
||||
}
|
||||
|
||||
|
||||
@Bean(name=ConfigurableApplicationContext.LOAD_TIME_WEAVER_BEAN_NAME)
|
||||
@Bean(name = ConfigurableApplicationContext.LOAD_TIME_WEAVER_BEAN_NAME)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public LoadTimeWeaver loadTimeWeaver() {
|
||||
LoadTimeWeaver loadTimeWeaver = null;
|
||||
@@ -87,7 +90,7 @@ public class LoadTimeWeavingConfiguration implements ImportAware, BeanClassLoade
|
||||
// AJ weaving is disabled -> do nothing
|
||||
break;
|
||||
case AUTODETECT:
|
||||
if (this.beanClassLoader.getResource(ASPECTJ_AOP_XML_RESOURCE) == null) {
|
||||
if (this.beanClassLoader.getResource(AspectJWeavingEnabler.ASPECTJ_AOP_XML_RESOURCE) == null) {
|
||||
// No aop.xml present on the classpath -> treat as 'disabled'
|
||||
break;
|
||||
}
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -51,7 +51,7 @@ public class MBeanExportConfiguration implements ImportAware, EnvironmentAware,
|
||||
|
||||
private static final String MBEAN_EXPORTER_BEAN_NAME = "mbeanExporter";
|
||||
|
||||
private AnnotationAttributes attributes;
|
||||
private AnnotationAttributes enableMBeanExport;
|
||||
|
||||
private Environment environment;
|
||||
|
||||
@@ -61,8 +61,8 @@ public class MBeanExportConfiguration implements ImportAware, EnvironmentAware,
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
Map<String, Object> map = importMetadata.getAnnotationAttributes(EnableMBeanExport.class.getName());
|
||||
this.attributes = AnnotationAttributes.fromMap(map);
|
||||
if (this.attributes == null) {
|
||||
this.enableMBeanExport = AnnotationAttributes.fromMap(map);
|
||||
if (this.enableMBeanExport == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"@EnableMBeanExport is not present on importing class " + importMetadata.getClassName());
|
||||
}
|
||||
@@ -90,7 +90,7 @@ public class MBeanExportConfiguration implements ImportAware, EnvironmentAware,
|
||||
}
|
||||
|
||||
private void setupDomain(AnnotationMBeanExporter exporter) {
|
||||
String defaultDomain = this.attributes.getString("defaultDomain");
|
||||
String defaultDomain = this.enableMBeanExport.getString("defaultDomain");
|
||||
if (defaultDomain != null && this.environment != null) {
|
||||
defaultDomain = this.environment.resolvePlaceholders(defaultDomain);
|
||||
}
|
||||
@@ -100,7 +100,7 @@ public class MBeanExportConfiguration implements ImportAware, EnvironmentAware,
|
||||
}
|
||||
|
||||
private void setupServer(AnnotationMBeanExporter exporter) {
|
||||
String server = this.attributes.getString("server");
|
||||
String server = this.enableMBeanExport.getString("server");
|
||||
if (server != null && this.environment != null) {
|
||||
server = this.environment.resolvePlaceholders(server);
|
||||
}
|
||||
@@ -116,7 +116,7 @@ public class MBeanExportConfiguration implements ImportAware, EnvironmentAware,
|
||||
}
|
||||
|
||||
private void setupRegistrationPolicy(AnnotationMBeanExporter exporter) {
|
||||
RegistrationPolicy registrationPolicy = this.attributes.getEnum("registration");
|
||||
RegistrationPolicy registrationPolicy = this.enableMBeanExport.getEnum("registration");
|
||||
exporter.setRegistrationPolicy(registrationPolicy);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,16 +28,16 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
||||
* Indicates the 'role' hint for a given bean.
|
||||
*
|
||||
* <p>May be used on any class directly or indirectly annotated with
|
||||
* {@link org.springframework.stereotype.Component} or on methods annotated with
|
||||
* {@link Bean}.
|
||||
* {@link org.springframework.stereotype.Component} or on methods
|
||||
* annotated with {@link Bean}.
|
||||
*
|
||||
* <p>If this annotation is not present on a Component or Bean definition, the
|
||||
* default value of {@link BeanDefinition#ROLE_APPLICATION} will apply.
|
||||
* <p>If this annotation is not present on a Component or Bean definition,
|
||||
* the default value of {@link BeanDefinition#ROLE_APPLICATION} will apply.
|
||||
*
|
||||
* <p>If Role is present on a {@link Configuration @Configuration} class, this
|
||||
* indicates the role of the configuration class bean definition and does not
|
||||
* cascade to all @{@code Bean} methods defined within. This behavior is
|
||||
* different than that of the @{@link Lazy} annotation, for example.
|
||||
* <p>If Role is present on a {@link Configuration @Configuration} class,
|
||||
* this indicates the role of the configuration class bean definition and
|
||||
* does not cascade to all @{@code Bean} methods defined within. This behavior
|
||||
* is different than that of the @{@link Lazy} annotation, for example.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
|
||||
+53
-45
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,6 +28,7 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.support.AbstractBeanFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.core.OrderComparator;
|
||||
@@ -65,47 +66,8 @@ public abstract class AbstractApplicationEventMulticaster
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private Object retrievalMutex = this.defaultRetriever;
|
||||
|
||||
@Override
|
||||
public void addApplicationListener(ApplicationListener<?> listener) {
|
||||
synchronized (this.defaultRetriever) {
|
||||
this.defaultRetriever.applicationListeners.add(listener);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addApplicationListenerBean(String listenerBeanName) {
|
||||
synchronized (this.defaultRetriever) {
|
||||
this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeApplicationListener(ApplicationListener<?> listener) {
|
||||
synchronized (this.defaultRetriever) {
|
||||
this.defaultRetriever.applicationListeners.remove(listener);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeApplicationListenerBean(String listenerBeanName) {
|
||||
synchronized (this.defaultRetriever) {
|
||||
this.defaultRetriever.applicationListenerBeans.remove(listenerBeanName);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllListeners() {
|
||||
synchronized (this.defaultRetriever) {
|
||||
this.defaultRetriever.applicationListeners.clear();
|
||||
this.defaultRetriever.applicationListenerBeans.clear();
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
@@ -118,6 +80,9 @@ public abstract class AbstractApplicationEventMulticaster
|
||||
if (this.beanClassLoader == null && beanFactory instanceof ConfigurableBeanFactory) {
|
||||
this.beanClassLoader = ((ConfigurableBeanFactory) beanFactory).getBeanClassLoader();
|
||||
}
|
||||
if (beanFactory instanceof AbstractBeanFactory) {
|
||||
this.retrievalMutex = ((AbstractBeanFactory) beanFactory).getSingletonMutex();
|
||||
}
|
||||
}
|
||||
|
||||
private BeanFactory getBeanFactory() {
|
||||
@@ -129,13 +94,55 @@ public abstract class AbstractApplicationEventMulticaster
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addApplicationListener(ApplicationListener<?> listener) {
|
||||
synchronized (this.retrievalMutex) {
|
||||
this.defaultRetriever.applicationListeners.add(listener);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addApplicationListenerBean(String listenerBeanName) {
|
||||
synchronized (this.retrievalMutex) {
|
||||
this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeApplicationListener(ApplicationListener<?> listener) {
|
||||
synchronized (this.retrievalMutex) {
|
||||
this.defaultRetriever.applicationListeners.remove(listener);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeApplicationListenerBean(String listenerBeanName) {
|
||||
synchronized (this.retrievalMutex) {
|
||||
this.defaultRetriever.applicationListenerBeans.remove(listenerBeanName);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllListeners() {
|
||||
synchronized (this.retrievalMutex) {
|
||||
this.defaultRetriever.applicationListeners.clear();
|
||||
this.defaultRetriever.applicationListenerBeans.clear();
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a Collection containing all ApplicationListeners.
|
||||
* @return a Collection of ApplicationListeners
|
||||
* @see org.springframework.context.ApplicationListener
|
||||
*/
|
||||
protected Collection<ApplicationListener<?>> getApplicationListeners() {
|
||||
synchronized (this.defaultRetriever) {
|
||||
synchronized (this.retrievalMutex) {
|
||||
return this.defaultRetriever.getApplicationListeners();
|
||||
}
|
||||
}
|
||||
@@ -163,13 +170,14 @@ public abstract class AbstractApplicationEventMulticaster
|
||||
(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
|
||||
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
|
||||
// Fully synchronized building and caching of a ListenerRetriever
|
||||
synchronized (this.defaultRetriever) {
|
||||
synchronized (this.retrievalMutex) {
|
||||
retriever = this.retrieverCache.get(cacheKey);
|
||||
if (retriever != null) {
|
||||
return retriever.getApplicationListeners();
|
||||
}
|
||||
retriever = new ListenerRetriever(true);
|
||||
Collection<ApplicationListener<?>> listeners = retrieveApplicationListeners(event, sourceType, retriever);
|
||||
Collection<ApplicationListener<?>> listeners =
|
||||
retrieveApplicationListeners(event, sourceType, retriever);
|
||||
this.retrieverCache.put(cacheKey, retriever);
|
||||
return listeners;
|
||||
}
|
||||
@@ -193,7 +201,7 @@ public abstract class AbstractApplicationEventMulticaster
|
||||
LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>();
|
||||
Set<ApplicationListener<?>> listeners;
|
||||
Set<String> listenerBeans;
|
||||
synchronized (this.defaultRetriever) {
|
||||
synchronized (this.retrievalMutex) {
|
||||
listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners);
|
||||
listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans);
|
||||
}
|
||||
|
||||
+8
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -152,7 +152,7 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
|
||||
* Set the default charset to use for parsing resource bundle files.
|
||||
* <p>Default is none, using the {@code java.util.ResourceBundle}
|
||||
* default encoding: ISO-8859-1.
|
||||
* and more flexibility in setting of an encoding per file.
|
||||
* @since 3.1.3
|
||||
*/
|
||||
public void setDefaultEncoding(String defaultEncoding) {
|
||||
this.defaultEncoding = defaultEncoding;
|
||||
@@ -167,6 +167,7 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
|
||||
* {@code java.util.ResourceBundle}. However, this is often not desirable
|
||||
* in an application server environment, where the system Locale is not relevant
|
||||
* to the application at all: Set this flag to "false" in such a scenario.
|
||||
* @since 3.1.3
|
||||
*/
|
||||
public void setFallbackToSystemLocale(boolean fallbackToSystemLocale) {
|
||||
this.fallbackToSystemLocale = fallbackToSystemLocale;
|
||||
@@ -188,6 +189,7 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
|
||||
* Consider {@link ReloadableResourceBundleMessageSource} in combination
|
||||
* with resource bundle files in a non-classpath location.
|
||||
* </ul>
|
||||
* @since 3.1.3
|
||||
*/
|
||||
public void setCacheSeconds(int cacheSeconds) {
|
||||
this.cacheMillis = (cacheSeconds * 1000);
|
||||
@@ -304,7 +306,7 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
|
||||
* @param locale the Locale to look for
|
||||
* @return the corresponding ResourceBundle
|
||||
* @throws MissingResourceException if no matching bundle could be found
|
||||
* @see java.util.ResourceBundle#getBundle(String, java.util.Locale, ClassLoader)
|
||||
* @see java.util.ResourceBundle#getBundle(String, Locale, ClassLoader)
|
||||
* @see #getBundleClassLoader()
|
||||
*/
|
||||
protected ResourceBundle doGetBundle(String basename, Locale locale) throws MissingResourceException {
|
||||
@@ -394,6 +396,8 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
|
||||
@Override
|
||||
public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
|
||||
throws IllegalAccessException, InstantiationException, IOException {
|
||||
|
||||
// Special handling of default encoding
|
||||
if (format.equals("java.properties")) {
|
||||
String bundleName = toBundleName(baseName, locale);
|
||||
final String resourceName = toResourceName(bundleName, "properties");
|
||||
@@ -441,6 +445,7 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Delegate handling of "java.class" format to standard Control
|
||||
return super.newBundle(baseName, locale, format, loader, reload);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.format.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -28,19 +29,19 @@ import java.lang.annotation.Target;
|
||||
* 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.
|
||||
* <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,
|
||||
* <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 the {@link #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).
|
||||
*
|
||||
@@ -49,8 +50,9 @@ import java.lang.annotation.Target;
|
||||
* @since 3.0
|
||||
* @see org.joda.time.format.DateTimeFormat
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
|
||||
public @interface DateTimeFormat {
|
||||
|
||||
/**
|
||||
@@ -80,23 +82,23 @@ public @interface DateTimeFormat {
|
||||
/**
|
||||
* Common ISO date time format patterns.
|
||||
*/
|
||||
public enum ISO {
|
||||
enum ISO {
|
||||
|
||||
/**
|
||||
* The most common ISO Date Format {@code yyyy-MM-dd},
|
||||
* e.g. 2000-10-31.
|
||||
* 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.
|
||||
* 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.
|
||||
* e.g. "2000-10-31 01:30:00.000-05:00".
|
||||
* <p>This is the default if no annotation value is specified.
|
||||
*/
|
||||
DATE_TIME,
|
||||
|
||||
+14
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.format.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -23,23 +24,27 @@ import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Declares that a field should be formatted as a number.
|
||||
* Supports formatting by style or custom pattern string.
|
||||
*
|
||||
* <p>Supports formatting by style or custom pattern string.
|
||||
* Can be applied to any JDK {@code java.lang.Number} type.
|
||||
*
|
||||
* <p>For style-based formatting, set the {@link #style()} attribute to be the desired {@link Style}.
|
||||
* For custom formatting, set the {@link #pattern()} attribute to be the number pattern, such as {@code #, ###.##}.
|
||||
* <p>For style-based formatting, set the {@link #style} attribute to be the
|
||||
* desired {@link Style}. For custom formatting, set the {@link #pattern}
|
||||
* attribute to be the number pattern, such as {@code #, ###.##}.
|
||||
*
|
||||
* <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 the style attribute. When no annotation attributes are specified,
|
||||
* <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 {@link #pattern} attribute is specified, it takes precedence over
|
||||
* the {@link #style} attribute. When no annotation attributes are specified,
|
||||
* the default format applied is style-based with a style of {@link Style#NUMBER}.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
* @see java.text.NumberFormat
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
|
||||
public @interface NumberFormat {
|
||||
|
||||
/**
|
||||
@@ -62,7 +67,7 @@ public @interface NumberFormat {
|
||||
/**
|
||||
* Common number format styles.
|
||||
*/
|
||||
public enum Style {
|
||||
enum Style {
|
||||
|
||||
/**
|
||||
* The general-purpose number format for the current locale.
|
||||
|
||||
+9
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -88,8 +88,8 @@ public class FormattingConversionService extends GenericConversionService
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void addFormatterForFieldAnnotation(AnnotationFormatterFactory annotationFormatterFactory) {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addFormatterForFieldAnnotation(AnnotationFormatterFactory<? extends Annotation> annotationFormatterFactory) {
|
||||
Class<? extends Annotation> annotationType = (Class<? extends Annotation>)
|
||||
GenericTypeResolver.resolveTypeArgument(annotationFormatterFactory.getClass(), AnnotationFormatterFactory.class);
|
||||
if (annotationType == null) {
|
||||
@@ -148,7 +148,7 @@ public class FormattingConversionService extends GenericConversionService
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.fieldType.getName() + " -> " + String.class.getName() + " : " + this.printer;
|
||||
return (this.fieldType.getName() + " -> " + String.class.getName() + " : " + this.printer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ public class FormattingConversionService extends GenericConversionService
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.class.getName() + " -> " + this.fieldType.getName() + ": " + this.parser;
|
||||
return (String.class.getName() + " -> " + this.fieldType.getName() + ": " + this.parser);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,8 +249,8 @@ public class FormattingConversionService extends GenericConversionService
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "@" + this.annotationType.getName() + " " + this.fieldType.getName() + " -> " +
|
||||
String.class.getName() + ": " + this.annotationFormatterFactory;
|
||||
return ("@" + this.annotationType.getName() + " " + this.fieldType.getName() + " -> " +
|
||||
String.class.getName() + ": " + this.annotationFormatterFactory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,8 +302,8 @@ public class FormattingConversionService extends GenericConversionService
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.class.getName() + " -> @" + this.annotationType.getName() + " " +
|
||||
this.fieldType.getName() + ": " + this.annotationFormatterFactory;
|
||||
return (String.class.getName() + " -> @" + this.annotationType.getName() + " " +
|
||||
this.fieldType.getName() + ": " + this.annotationFormatterFactory);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ public class MBeanExporter extends MBeanRegistrationSupport implements MBeanExpo
|
||||
private boolean exposeManagedResourceClassLoader = true;
|
||||
|
||||
/** A set of bean names that should be excluded from autodetection */
|
||||
private Set<String> excludedBeans;
|
||||
private Set<String> excludedBeans = new HashSet<String>();
|
||||
|
||||
/** The MBeanExporterListeners registered with this exporter. */
|
||||
private MBeanExporterListener[] listeners;
|
||||
@@ -314,7 +314,18 @@ public class MBeanExporter extends MBeanRegistrationSupport implements MBeanExpo
|
||||
* Set the list of names for beans that should be excluded from autodetection.
|
||||
*/
|
||||
public void setExcludedBeans(String... excludedBeans) {
|
||||
this.excludedBeans = (excludedBeans != null ? new HashSet<String>(Arrays.asList(excludedBeans)) : null);
|
||||
this.excludedBeans.clear();
|
||||
if (excludedBeans != null) {
|
||||
this.excludedBeans.addAll(Arrays.asList(excludedBeans));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the name of bean that should be excluded from autodetection.
|
||||
*/
|
||||
public void addExcludedBean(String excludedBean) {
|
||||
Assert.notNull(excludedBean, "ExcludedBean must not be null");
|
||||
this.excludedBeans.add(excludedBean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -922,10 +933,9 @@ public class MBeanExporter extends MBeanRegistrationSupport implements MBeanExpo
|
||||
* Indicates whether or not a particular bean name is present in the excluded beans list.
|
||||
*/
|
||||
private boolean isExcluded(String beanName) {
|
||||
return (this.excludedBeans != null &&
|
||||
(this.excludedBeans.contains(beanName) ||
|
||||
(beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX) &&
|
||||
this.excludedBeans.contains(beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length())))));
|
||||
return (this.excludedBeans.contains(beanName) ||
|
||||
(beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX) &&
|
||||
this.excludedBeans.contains(beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length()))));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+7
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,7 +25,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
@@ -43,6 +42,7 @@ public abstract class AbstractAsyncConfiguration implements ImportAware {
|
||||
protected AnnotationAttributes enableAsync;
|
||||
|
||||
protected Executor executor;
|
||||
|
||||
protected AsyncUncaughtExceptionHandler exceptionHandler;
|
||||
|
||||
|
||||
@@ -50,14 +50,16 @@ public abstract class AbstractAsyncConfiguration implements ImportAware {
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
this.enableAsync = AnnotationAttributes.fromMap(
|
||||
importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false));
|
||||
Assert.notNull(this.enableAsync,
|
||||
"@EnableAsync is not present on importing class " + importMetadata.getClassName());
|
||||
if (this.enableAsync == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"@EnableAsync is not present on importing class " + importMetadata.getClassName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect any {@link AsyncConfigurer} beans through autowiring.
|
||||
*/
|
||||
@Autowired(required=false)
|
||||
@Autowired(required = false)
|
||||
void setConfigurers(Collection<AsyncConfigurer> configurers) {
|
||||
if (CollectionUtils.isEmpty(configurers)) {
|
||||
return;
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {
|
||||
public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
|
||||
Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
|
||||
AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
|
||||
Class<? extends Annotation> customAsyncAnnotation = enableAsync.getClass("annotation");
|
||||
Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
|
||||
if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
|
||||
bpp.setAsyncAnnotationType(customAsyncAnnotation);
|
||||
}
|
||||
|
||||
+38
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,7 +39,10 @@ import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
@@ -61,12 +64,12 @@ import org.springframework.util.StringValueResolver;
|
||||
* to the "fixedRate", "fixedDelay", or "cron" expression provided via the annotation.
|
||||
*
|
||||
* <p>This post-processor is automatically registered by Spring's
|
||||
* {@code <task:annotation-driven>} XML element, and also by the @{@link EnableScheduling}
|
||||
* annotation.
|
||||
* {@code <task:annotation-driven>} XML element, and also by the
|
||||
* @{@link EnableScheduling} annotation.
|
||||
*
|
||||
* <p>Auto-detects any {@link SchedulingConfigurer} instances in the container,
|
||||
* allowing for customization of the scheduler to be used or for fine-grained control
|
||||
* over task registration (e.g. registration of {@link Trigger} tasks.
|
||||
* <p>Autodetects any {@link SchedulingConfigurer} instances in the container,
|
||||
* allowing for customization of the scheduler to be used or for fine-grained
|
||||
* control over task registration (e.g. registration of {@link Trigger} tasks.
|
||||
* See the @{@link EnableScheduling} javadocs for complete usage details.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
@@ -80,7 +83,8 @@ import org.springframework.util.StringValueResolver;
|
||||
* @see org.springframework.scheduling.config.ScheduledTaskRegistrar
|
||||
*/
|
||||
public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor, Ordered,
|
||||
EmbeddedValueResolverAware, BeanFactoryAware, SmartInitializingSingleton, DisposableBean {
|
||||
EmbeddedValueResolverAware, BeanFactoryAware, ApplicationContextAware,
|
||||
SmartInitializingSingleton, ApplicationListener<ContextRefreshedEvent>, DisposableBean {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@@ -90,6 +94,8 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private final ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar();
|
||||
|
||||
private final Set<Class<?>> nonAnnotatedClasses =
|
||||
@@ -126,10 +132,13 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated as of Spring 4.1, in favor of {@link #setBeanFactory}
|
||||
* Setting an {@link ApplicationContext} is optional: If set, registered
|
||||
* tasks will be activated in the {@link ContextRefreshedEvent} phase;
|
||||
* if not set, it will happen at {@link #afterSingletonsInstantiated} time.
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
if (this.beanFactory == null) {
|
||||
this.beanFactory = applicationContext;
|
||||
}
|
||||
@@ -138,6 +147,23 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
if (this.applicationContext == null) {
|
||||
// Not running in an ApplicationContext -> register tasks early...
|
||||
finishRegistration();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
if (event.getApplicationContext() == this.applicationContext) {
|
||||
// Running in an ApplicationContext -> register tasks this late...
|
||||
// giving other ContextRefreshedEvent listeners a chance to perform
|
||||
// their work at the same time (e.g. Spring Batch's job registration).
|
||||
finishRegistration();
|
||||
}
|
||||
}
|
||||
|
||||
private void finishRegistration() {
|
||||
if (this.scheduler != null) {
|
||||
this.registrar.setScheduler(this.scheduler);
|
||||
}
|
||||
@@ -190,9 +216,9 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(final Object bean, String beanName) {
|
||||
if (!this.nonAnnotatedClasses.contains(bean.getClass())) {
|
||||
Class<?> targetClass = AopUtils.getTargetClass(bean);
|
||||
if (!this.nonAnnotatedClasses.contains(targetClass)) {
|
||||
final Set<Method> annotatedMethods = new LinkedHashSet<Method>(1);
|
||||
Class<?> targetClass = AopUtils.getTargetClass(bean);
|
||||
ReflectionUtils.doWithMethods(targetClass, new MethodCallback() {
|
||||
@Override
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
@@ -204,7 +230,7 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
|
||||
}
|
||||
});
|
||||
if (annotatedMethods.isEmpty()) {
|
||||
this.nonAnnotatedClasses.add(bean.getClass());
|
||||
this.nonAnnotatedClasses.add(targetClass);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No @Scheduled annotations found on bean class: " + bean.getClass());
|
||||
}
|
||||
|
||||
+17
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,11 +32,14 @@ import org.springframework.jndi.JndiTemplate;
|
||||
* for JSR-236's "java:comp/DefaultManagedThreadFactory" in a Java EE 7 environment,
|
||||
* falling back to the local {@link CustomizableThreadFactory} setup if not found.
|
||||
*
|
||||
* <p>This is a convenient way to use managed threads when running in a Java EE 7 environment,
|
||||
* simply using regular local threads otherwise - without conditional setup (like profiles).
|
||||
* <p>This is a convenient way to use managed threads when running in a Java EE 7
|
||||
* environment, simply using regular local threads otherwise - without conditional
|
||||
* setup (i.e. without profiles).
|
||||
*
|
||||
* <p>Note: This class is not strictly JSR-236 based; it can work with any regular
|
||||
* {@link java.util.concurrent.ThreadFactory} that can be found in JNDI.
|
||||
* {@link java.util.concurrent.ThreadFactory} that can be found in JNDI. Therefore,
|
||||
* the default JNDI name "java:comp/DefaultManagedThreadFactory" can be customized
|
||||
* through the {@link #setJndiName "jndiName"} bean property.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
@@ -50,7 +53,7 @@ public class DefaultManagedAwareThreadFactory extends CustomizableThreadFactory
|
||||
|
||||
private String jndiName = "java:comp/DefaultManagedThreadFactory";
|
||||
|
||||
private ThreadFactory threadFactory = this;
|
||||
private ThreadFactory threadFactory;
|
||||
|
||||
|
||||
/**
|
||||
@@ -98,12 +101,10 @@ public class DefaultManagedAwareThreadFactory extends CustomizableThreadFactory
|
||||
}
|
||||
catch (NamingException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to find [java:comp/DefaultManagedThreadFactory] in JNDI", ex);
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Could not find default managed thread factory in JNDI - " +
|
||||
"proceeding with default local thread factory");
|
||||
logger.debug("Failed to retrieve [" + this.jndiName + "] from JNDI", ex);
|
||||
}
|
||||
logger.info("Could not find default managed thread factory in JNDI - " +
|
||||
"proceeding with default local thread factory");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,7 +112,12 @@ public class DefaultManagedAwareThreadFactory extends CustomizableThreadFactory
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable runnable) {
|
||||
return this.threadFactory.newThread(runnable);
|
||||
if (this.threadFactory != null) {
|
||||
return this.threadFactory.newThread(runnable);
|
||||
}
|
||||
else {
|
||||
return super.newThread(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+42
-29
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,7 +29,8 @@ import java.util.TimeZone;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Date sequence generator for a <a href="http://www.manpagez.com/man/5/crontab/">Crontab pattern</a>,
|
||||
* Date sequence generator for a
|
||||
* <a href="http://www.manpagez.com/man/5/crontab/">Crontab pattern</a>,
|
||||
* allowing clients to specify a pattern that the sequence matches.
|
||||
*
|
||||
* <p>The pattern is a list of six single space-separated fields: representing
|
||||
@@ -53,22 +54,22 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class CronSequenceGenerator {
|
||||
|
||||
private final BitSet seconds = new BitSet(60);
|
||||
|
||||
private final BitSet minutes = new BitSet(60);
|
||||
|
||||
private final BitSet hours = new BitSet(24);
|
||||
|
||||
private final BitSet daysOfWeek = new BitSet(7);
|
||||
|
||||
private final BitSet daysOfMonth = new BitSet(31);
|
||||
|
||||
private final BitSet months = new BitSet(12);
|
||||
|
||||
private final String expression;
|
||||
|
||||
private final TimeZone timeZone;
|
||||
|
||||
private final BitSet months = new BitSet(12);
|
||||
|
||||
private final BitSet daysOfMonth = new BitSet(31);
|
||||
|
||||
private final BitSet daysOfWeek = new BitSet(7);
|
||||
|
||||
private final BitSet hours = new BitSet(24);
|
||||
|
||||
private final BitSet minutes = new BitSet(60);
|
||||
|
||||
private final BitSet seconds = new BitSet(60);
|
||||
|
||||
|
||||
/**
|
||||
* Construct a {@link CronSequenceGenerator} from the pattern provided,
|
||||
@@ -95,6 +96,14 @@ public class CronSequenceGenerator {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the cron pattern that this sequence generator has been built for.
|
||||
*/
|
||||
String getExpression() {
|
||||
return this.expression;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next {@link Date} in the sequence matching the Cron pattern and
|
||||
* after the value provided. The return value will have a whole number of
|
||||
@@ -271,9 +280,9 @@ public class CronSequenceGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the values in the commaSeparatedList (case insensitive) with
|
||||
* their index in the list.
|
||||
* @return a new string with the values from the list replaced
|
||||
* Replace the values in the comma-separated list (case insensitive)
|
||||
* with their index in the list.
|
||||
* @return a new String with the values from the list replaced
|
||||
*/
|
||||
private String replaceOrdinals(String value, String commaSeparatedList) {
|
||||
String[] list = StringUtils.commaDelimitedListToStringArray(commaSeparatedList);
|
||||
@@ -332,6 +341,10 @@ public class CronSequenceGenerator {
|
||||
range[1] = max - 1;
|
||||
}
|
||||
int delta = Integer.valueOf(split[1]);
|
||||
if (delta <= 0) {
|
||||
throw new IllegalArgumentException("Incrementer delta must be 1 or higher: '" +
|
||||
field + "' in expression \"" + this.expression + "\"");
|
||||
}
|
||||
for (int i = range[0]; i <= range[1]; i += delta) {
|
||||
bits.set(i);
|
||||
}
|
||||
@@ -369,30 +382,30 @@ public class CronSequenceGenerator {
|
||||
return result;
|
||||
}
|
||||
|
||||
String getExpression() {
|
||||
return this.expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof CronSequenceGenerator)) {
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof CronSequenceGenerator)) {
|
||||
return false;
|
||||
}
|
||||
CronSequenceGenerator cron = (CronSequenceGenerator) obj;
|
||||
return cron.months.equals(this.months) && cron.daysOfMonth.equals(this.daysOfMonth)
|
||||
&& cron.daysOfWeek.equals(this.daysOfWeek) && cron.hours.equals(this.hours)
|
||||
&& cron.minutes.equals(this.minutes) && cron.seconds.equals(this.seconds);
|
||||
CronSequenceGenerator otherCron = (CronSequenceGenerator) other;
|
||||
return (this.months.equals(otherCron.months) && this.daysOfMonth.equals(otherCron.daysOfMonth) &&
|
||||
this.daysOfWeek.equals(otherCron.daysOfWeek) && this.hours.equals(otherCron.hours) &&
|
||||
this.minutes.equals(otherCron.minutes) && this.seconds.equals(otherCron.seconds));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 37 + 17 * this.months.hashCode() + 29 * this.daysOfMonth.hashCode() + 37 * this.daysOfWeek.hashCode()
|
||||
+ 41 * this.hours.hashCode() + 53 * this.minutes.hashCode() + 61 * this.seconds.hashCode();
|
||||
return (17 * this.months.hashCode() + 29 * this.daysOfMonth.hashCode() + 37 * this.daysOfWeek.hashCode() +
|
||||
41 * this.hours.hashCode() + 53 * this.minutes.hashCode() + 61 * this.seconds.hashCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + ": " + this.expression;
|
||||
return (getClass().getSimpleName() + ": " + this.expression);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+21
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,21 +37,29 @@ public class CronTrigger implements Trigger {
|
||||
|
||||
/**
|
||||
* Build a {@link CronTrigger} from the pattern provided in the default time zone.
|
||||
* @param cronExpression a space-separated list of time fields,
|
||||
* following cron expression conventions
|
||||
* @param expression a space-separated list of time fields, following cron
|
||||
* expression conventions
|
||||
*/
|
||||
public CronTrigger(String cronExpression) {
|
||||
this.sequenceGenerator = new CronSequenceGenerator(cronExpression);
|
||||
public CronTrigger(String expression) {
|
||||
this.sequenceGenerator = new CronSequenceGenerator(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link CronTrigger} from the pattern provided.
|
||||
* @param cronExpression a space-separated list of time fields,
|
||||
* following cron expression conventions
|
||||
* Build a {@link CronTrigger} from the pattern provided in the given time zone.
|
||||
* @param expression a space-separated list of time fields, following cron
|
||||
* expression conventions
|
||||
* @param timeZone a time zone in which the trigger times will be generated
|
||||
*/
|
||||
public CronTrigger(String cronExpression, TimeZone timeZone) {
|
||||
this.sequenceGenerator = new CronSequenceGenerator(cronExpression, timeZone);
|
||||
public CronTrigger(String expression, TimeZone timeZone) {
|
||||
this.sequenceGenerator = new CronSequenceGenerator(expression, timeZone);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the cron pattern that this trigger has been built with.
|
||||
*/
|
||||
public String getExpression() {
|
||||
return this.sequenceGenerator.getExpression();
|
||||
}
|
||||
|
||||
|
||||
@@ -79,14 +87,11 @@ public class CronTrigger implements Trigger {
|
||||
return this.sequenceGenerator.next(date);
|
||||
}
|
||||
|
||||
public String getExpression() {
|
||||
return this.sequenceGenerator.getExpression();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj || (obj instanceof CronTrigger &&
|
||||
this.sequenceGenerator.equals(((CronTrigger) obj).sequenceGenerator)));
|
||||
public boolean equals(Object other) {
|
||||
return (this == other || (other instanceof CronTrigger &&
|
||||
this.sequenceGenerator.equals(((CronTrigger) other).sequenceGenerator)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,7 +24,6 @@ import groovy.lang.MetaClass;
|
||||
import groovy.lang.Script;
|
||||
import org.codehaus.groovy.control.CompilationFailedException;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
@@ -102,7 +101,7 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea
|
||||
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (beanFactory instanceof ConfigurableListableBeanFactory) {
|
||||
((ConfigurableListableBeanFactory) beanFactory).ignoreDependencyType(MetaClass.class);
|
||||
}
|
||||
|
||||
+11
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -94,7 +94,7 @@ import org.springframework.util.StringUtils;
|
||||
* <property name="message" value="Hello World!"/>
|
||||
* </bean>
|
||||
*
|
||||
* <bean id="groovyMessenger" class="org.springframework.scripting.bsh.GroovyScriptFactory">
|
||||
* <bean id="groovyMessenger" class="org.springframework.scripting.groovy.GroovyScriptFactory">
|
||||
* <constructor-arg value="classpath:mypackage/Messenger.groovy"/>
|
||||
* <property name="message" value="Hello World!"/>
|
||||
* </bean></pre>
|
||||
@@ -346,17 +346,16 @@ public class ScriptFactoryPostProcessor extends InstantiationAwareBeanPostProces
|
||||
* @param scriptedObjectBeanName the name of the internal scripted object bean
|
||||
*/
|
||||
protected void prepareScriptBeans(BeanDefinition bd, String scriptFactoryBeanName, String scriptedObjectBeanName) {
|
||||
|
||||
// Avoid recreation of the script bean definition in case of a prototype.
|
||||
synchronized (this.scriptBeanFactory) {
|
||||
if (!this.scriptBeanFactory.containsBeanDefinition(scriptedObjectBeanName)) {
|
||||
|
||||
this.scriptBeanFactory.registerBeanDefinition(scriptFactoryBeanName,
|
||||
createScriptFactoryBeanDefinition(bd));
|
||||
ScriptFactory scriptFactory = this.scriptBeanFactory
|
||||
.getBean(scriptFactoryBeanName, ScriptFactory.class);
|
||||
ScriptSource scriptSource = getScriptSource(scriptFactoryBeanName,
|
||||
scriptFactory.getScriptSourceLocator());
|
||||
this.scriptBeanFactory.registerBeanDefinition(
|
||||
scriptFactoryBeanName, createScriptFactoryBeanDefinition(bd));
|
||||
ScriptFactory scriptFactory =
|
||||
this.scriptBeanFactory.getBean(scriptFactoryBeanName, ScriptFactory.class);
|
||||
ScriptSource scriptSource =
|
||||
getScriptSource(scriptFactoryBeanName, scriptFactory.getScriptSourceLocator());
|
||||
Class<?>[] interfaces = scriptFactory.getScriptInterfaces();
|
||||
|
||||
Class<?>[] scriptedInterfaces = interfaces;
|
||||
@@ -365,8 +364,8 @@ public class ScriptFactoryPostProcessor extends InstantiationAwareBeanPostProces
|
||||
scriptedInterfaces = ObjectUtils.addObjectToArray(interfaces, configInterface);
|
||||
}
|
||||
|
||||
BeanDefinition objectBd = createScriptedObjectBeanDefinition(bd, scriptFactoryBeanName, scriptSource,
|
||||
scriptedInterfaces);
|
||||
BeanDefinition objectBd = createScriptedObjectBeanDefinition(
|
||||
bd, scriptFactoryBeanName, scriptSource, scriptedInterfaces);
|
||||
long refreshCheckDelay = resolveRefreshCheckDelay(bd);
|
||||
if (refreshCheckDelay >= 0) {
|
||||
objectBd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
@@ -569,7 +568,7 @@ public class ScriptFactoryPostProcessor extends InstantiationAwareBeanPostProces
|
||||
proxyFactory.setInterfaces(interfaces);
|
||||
if (proxyTargetClass) {
|
||||
classLoader = null; // force use of Class.getClassLoader()
|
||||
proxyFactory.setProxyTargetClass(proxyTargetClass);
|
||||
proxyFactory.setProxyTargetClass(true);
|
||||
}
|
||||
|
||||
DelegatingIntroductionInterceptor introduction = new DelegatingIntroductionInterceptor(ts);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -553,6 +553,7 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
return Collections.unmodifiableList(this.validators);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of PropertyEditorRegistry/TypeConverter interface
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
+9
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,10 +35,12 @@ import static org.junit.Assert.*;
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class BeanNamePointcutAtAspectTests {
|
||||
public class BeanNamePointcutAtAspectTests {
|
||||
|
||||
private ITestBean testBean1;
|
||||
|
||||
private ITestBean testBean3;
|
||||
|
||||
private CounterAspect counterAspect;
|
||||
|
||||
|
||||
@@ -46,7 +48,8 @@ public final class BeanNamePointcutAtAspectTests {
|
||||
@SuppressWarnings("resource")
|
||||
public void setUp() {
|
||||
ClassPathXmlApplicationContext ctx =
|
||||
new ClassPathXmlApplicationContext(getClass().getSimpleName() + ".xml", getClass());
|
||||
new ClassPathXmlApplicationContext(getClass().getSimpleName() + ".xml", getClass());
|
||||
|
||||
counterAspect = (CounterAspect) ctx.getBean("counterAspect");
|
||||
testBean1 = (ITestBean) ctx.getBean("testBean1");
|
||||
testBean3 = (ITestBean) ctx.getBean("testBean3");
|
||||
@@ -55,15 +58,17 @@ public final class BeanNamePointcutAtAspectTests {
|
||||
@Test
|
||||
public void testMatchingBeanName() {
|
||||
assertTrue("Expected a proxy", testBean1 instanceof Advised);
|
||||
|
||||
// Call two methods to test for SPR-3953-like condition
|
||||
testBean1.setAge(20);
|
||||
testBean1.setName("");
|
||||
assertEquals(2 /*TODO: make this 3 when upgrading to AspectJ 1.6.0 and advice in CounterAspect are uncommented*/, counterAspect.count);
|
||||
assertEquals(2, counterAspect.count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonMatchingBeanName() {
|
||||
assertFalse("Didn't expect a proxy", testBean3 instanceof Advised);
|
||||
|
||||
testBean3.setAge(20);
|
||||
assertEquals(0, counterAspect.count);
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,10 +35,11 @@ public class ClassWithComplexConstructor {
|
||||
}
|
||||
|
||||
public Dependency getDependency() {
|
||||
return dependency;
|
||||
return this.dependency;
|
||||
}
|
||||
|
||||
public void method() {
|
||||
this.dependency.method();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,8 +34,6 @@ public class ObjenesisProxyTests {
|
||||
|
||||
@Test
|
||||
public void appliesAspectToClassWithComplexConstructor() {
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext("ObjenesisProxyTests-context.xml", getClass());
|
||||
|
||||
ClassWithComplexConstructor bean = context.getBean(ClassWithComplexConstructor.class);
|
||||
@@ -45,4 +43,5 @@ public class ObjenesisProxyTests {
|
||||
assertThat(interceptor.getCount(), is(1L));
|
||||
assertThat(bean.getDependency().getValue(), is(1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -667,27 +667,27 @@ public class InjectAnnotationAutowireContextTests {
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Qualifier
|
||||
public static @interface TestQualifier {
|
||||
public @interface TestQualifier {
|
||||
}
|
||||
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Qualifier
|
||||
public static @interface TestQualifierWithDefaultValue {
|
||||
public @interface TestQualifierWithDefaultValue {
|
||||
|
||||
public abstract String value() default "default";
|
||||
String value() default "default";
|
||||
}
|
||||
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Qualifier
|
||||
public static @interface TestQualifierWithMultipleAttributes {
|
||||
public @interface TestQualifierWithMultipleAttributes {
|
||||
|
||||
public abstract String value() default "default";
|
||||
String value() default "default";
|
||||
|
||||
public abstract int number();
|
||||
int number();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+80
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,17 +17,24 @@
|
||||
package org.springframework.cache;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||
import org.springframework.cache.interceptor.AbstractCacheResolver;
|
||||
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
|
||||
import org.springframework.cache.interceptor.CacheResolver;
|
||||
import org.springframework.cache.support.SimpleCacheManager;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -45,6 +52,9 @@ import static org.mockito.Mockito.*;
|
||||
*/
|
||||
public class CacheReproTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void spr11124() throws Exception {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Spr11124Config.class);
|
||||
@@ -83,7 +93,7 @@ public class CacheReproTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void spr11592GetNeverCache(){
|
||||
public void spr11592GetNeverCache() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Spr11592Config.class);
|
||||
Spr11592Service bean = context.getBean(Spr11592Service.class);
|
||||
Cache cache = context.getBean("cache", Cache.class);
|
||||
@@ -99,6 +109,27 @@ public class CacheReproTests {
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void spr13081ConfigNoCacheNameIsRequired() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Spr13081Config.class);
|
||||
MyCacheResolver cacheResolver = context.getBean(MyCacheResolver.class);
|
||||
Spr13081Service bean = context.getBean(Spr13081Service.class);
|
||||
assertNull(cacheResolver.getCache("foo").get("foo"));
|
||||
Object result = bean.getSimple("foo"); // cache name = id
|
||||
assertEquals(result, cacheResolver.getCache("foo").get("foo").get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void spr13081ConfigFailIfCacheResolverReturnsNullCacheName() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Spr13081Config.class);
|
||||
Spr13081Service bean = context.getBean(Spr13081Service.class);
|
||||
|
||||
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage(MyCacheResolver.class.getName());
|
||||
bean.getSimple(null);
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
@@ -118,9 +149,9 @@ public class CacheReproTests {
|
||||
|
||||
public interface Spr11124Service {
|
||||
|
||||
public List<String> single(int id);
|
||||
List<String> single(int id);
|
||||
|
||||
public List<String> multiple(int id);
|
||||
List<String> multiple(int id);
|
||||
}
|
||||
|
||||
|
||||
@@ -214,4 +245,49 @@ public class CacheReproTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
public static class Spr13081Config extends CachingConfigurerSupport {
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public CacheResolver cacheResolver() {
|
||||
return new MyCacheResolver();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Spr13081Service service() {
|
||||
return new Spr13081Service();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class MyCacheResolver extends AbstractCacheResolver {
|
||||
|
||||
public MyCacheResolver() {
|
||||
super(new ConcurrentMapCacheManager());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<String> getCacheNames(CacheOperationInvocationContext<?> context) {
|
||||
String cacheName = (String) context.getArgs()[0];
|
||||
if (cacheName != null) {
|
||||
return Collections.singleton(cacheName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Cache getCache(String name) {
|
||||
return getCacheManager().getCache(name);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Spr13081Service {
|
||||
|
||||
@Cacheable
|
||||
public Object getSimple(String cacheName) {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -191,9 +191,12 @@ public class AnnotationCacheOperationSourceTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateAtLeastOneCacheNameMustBeSet() {
|
||||
thrown.expect(IllegalStateException.class);
|
||||
getOps(AnnotatedClass.class, "noCacheNameSpecified");
|
||||
public void validateNoCacheIsValid() {
|
||||
// Valid as a CacheResolver might return the cache names to use with other info
|
||||
Collection<CacheOperation> ops = getOps(AnnotatedClass.class, "noCacheNameSpecified");
|
||||
CacheOperation cacheOperation = ops.iterator().next();
|
||||
assertNotNull("cache names set must not be null", cacheOperation.getCacheNames());
|
||||
assertEquals("no cache names specified", 0, cacheOperation.getCacheNames().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+79
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,7 @@ import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -39,6 +40,7 @@ import static org.junit.Assert.*;
|
||||
* Test for {@link Conditional} beans.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
public class ConfigurationClassWithConditionTests {
|
||||
@@ -117,6 +119,29 @@ public class ConfigurationClassWithConditionTests {
|
||||
ctx.refresh();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void conditionOnOverriddenMethodHonored() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigWithBeanSkipped.class);
|
||||
assertEquals(0, context.getBeansOfType(ExampleBean.class).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noConditionOnOverriddenMethodHonored() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigWithBeanReactivated.class);
|
||||
Map<String, ExampleBean> beans = context.getBeansOfType(ExampleBean.class);
|
||||
assertEquals(1, beans.size());
|
||||
assertEquals("baz", beans.keySet().iterator().next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configWithAlternativeBeans() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigWithAlternativeBeans.class);
|
||||
Map<String, ExampleBean> beans = context.getBeansOfType(ExampleBean.class);
|
||||
assertEquals(1, beans.size());
|
||||
assertEquals("baz", beans.keySet().iterator().next());
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class BeanOneConfiguration {
|
||||
@Bean
|
||||
@@ -197,12 +222,21 @@ public class ConfigurationClassWithConditionTests {
|
||||
}
|
||||
|
||||
static class NeverCondition implements Condition {
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static class AlwaysCondition implements Condition {
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
@Never
|
||||
static class NonConfigurationClass {
|
||||
@@ -261,4 +295,48 @@ public class ConfigurationClassWithConditionTests {
|
||||
static class ExampleBean {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ConfigWithBeanActive {
|
||||
|
||||
@Bean
|
||||
public ExampleBean baz() {
|
||||
return new ExampleBean();
|
||||
}
|
||||
}
|
||||
|
||||
static class ConfigWithBeanSkipped extends ConfigWithBeanActive {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
@Conditional(NeverCondition.class)
|
||||
public ExampleBean baz() {
|
||||
return new ExampleBean();
|
||||
}
|
||||
}
|
||||
|
||||
static class ConfigWithBeanReactivated extends ConfigWithBeanSkipped {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public ExampleBean baz() {
|
||||
return new ExampleBean();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ConfigWithAlternativeBeans {
|
||||
|
||||
@Bean(name = "baz")
|
||||
@Conditional(AlwaysCondition.class)
|
||||
public ExampleBean baz1() {
|
||||
return new ExampleBean();
|
||||
}
|
||||
|
||||
@Bean(name = "baz")
|
||||
@Conditional(NeverCondition.class)
|
||||
public ExampleBean baz2() {
|
||||
return new ExampleBean();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+161
-135
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,13 +19,17 @@ package org.springframework.context.annotation;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests cornering bug SPR-8514.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
public class ConfigurationWithFactoryBeanAndAutowiringTests {
|
||||
@@ -77,138 +81,160 @@ public class ConfigurationWithFactoryBeanAndAutowiringTests {
|
||||
ctx.register(WildcardParameterizedFactoryBeanInterfaceConfig.class);
|
||||
ctx.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class DummyBean {
|
||||
}
|
||||
|
||||
|
||||
class MyFactoryBean implements FactoryBean<String> {
|
||||
@Override
|
||||
public String getObject() throws Exception {
|
||||
return "foo";
|
||||
}
|
||||
@Override
|
||||
public Class<String> getObjectType() {
|
||||
return String.class;
|
||||
}
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class MyParameterizedFactoryBean<T> implements FactoryBean<T> {
|
||||
|
||||
private final T obj;
|
||||
|
||||
public MyParameterizedFactoryBean(T obj) {
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getObject() throws Exception {
|
||||
return obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<T> getObjectType() {
|
||||
return (Class<T>)obj.getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
class AppConfig {
|
||||
@Bean
|
||||
public DummyBean dummyBean() {
|
||||
return new DummyBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
class ConcreteFactoryBeanImplementationConfig {
|
||||
@Autowired
|
||||
private DummyBean dummyBean;
|
||||
|
||||
@Bean
|
||||
public MyFactoryBean factoryBean() {
|
||||
Assert.notNull(dummyBean, "DummyBean was not injected.");
|
||||
return new MyFactoryBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
class ParameterizedFactoryBeanImplementationConfig {
|
||||
@Autowired
|
||||
private DummyBean dummyBean;
|
||||
|
||||
@Bean
|
||||
public MyParameterizedFactoryBean<String> factoryBean() {
|
||||
Assert.notNull(dummyBean, "DummyBean was not injected.");
|
||||
return new MyParameterizedFactoryBean<String>("whatev");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
class ParameterizedFactoryBeanInterfaceConfig {
|
||||
@Autowired
|
||||
private DummyBean dummyBean;
|
||||
|
||||
@Bean
|
||||
public FactoryBean<String> factoryBean() {
|
||||
Assert.notNull(dummyBean, "DummyBean was not injected.");
|
||||
return new MyFactoryBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
class NonPublicParameterizedFactoryBeanInterfaceConfig {
|
||||
@Autowired
|
||||
private DummyBean dummyBean;
|
||||
|
||||
@Bean
|
||||
FactoryBean<String> factoryBean() {
|
||||
Assert.notNull(dummyBean, "DummyBean was not injected.");
|
||||
return new MyFactoryBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
class RawFactoryBeanInterfaceConfig {
|
||||
@Autowired
|
||||
private DummyBean dummyBean;
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("rawtypes")
|
||||
public FactoryBean factoryBean() {
|
||||
Assert.notNull(dummyBean, "DummyBean was not injected.");
|
||||
return new MyFactoryBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
class WildcardParameterizedFactoryBeanInterfaceConfig {
|
||||
@Autowired
|
||||
private DummyBean dummyBean;
|
||||
|
||||
@Bean
|
||||
public FactoryBean<?> factoryBean() {
|
||||
Assert.notNull(dummyBean, "DummyBean was not injected.");
|
||||
return new MyFactoryBean();
|
||||
}
|
||||
|
||||
|
||||
static class DummyBean {
|
||||
}
|
||||
|
||||
|
||||
static class MyFactoryBean implements FactoryBean<String>, InitializingBean {
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getObject() throws Exception {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<String> getObjectType() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getString() {
|
||||
return Boolean.toString(this.initialized);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class MyParameterizedFactoryBean<T> implements FactoryBean<T> {
|
||||
|
||||
private final T obj;
|
||||
|
||||
public MyParameterizedFactoryBean(T obj) {
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getObject() throws Exception {
|
||||
return obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<T> getObjectType() {
|
||||
return (Class<T>)obj.getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class AppConfig {
|
||||
|
||||
@Bean
|
||||
public DummyBean dummyBean() {
|
||||
return new DummyBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class ConcreteFactoryBeanImplementationConfig {
|
||||
|
||||
@Autowired
|
||||
private DummyBean dummyBean;
|
||||
|
||||
@Bean
|
||||
public MyFactoryBean factoryBean() {
|
||||
Assert.notNull(dummyBean, "DummyBean was not injected.");
|
||||
return new MyFactoryBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class ParameterizedFactoryBeanImplementationConfig {
|
||||
|
||||
@Autowired
|
||||
private DummyBean dummyBean;
|
||||
|
||||
@Bean
|
||||
public MyParameterizedFactoryBean<String> factoryBean() {
|
||||
Assert.notNull(dummyBean, "DummyBean was not injected.");
|
||||
return new MyParameterizedFactoryBean<String>("whatev");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class ParameterizedFactoryBeanInterfaceConfig {
|
||||
|
||||
@Autowired
|
||||
private DummyBean dummyBean;
|
||||
|
||||
@Bean
|
||||
public FactoryBean<String> factoryBean() {
|
||||
Assert.notNull(dummyBean, "DummyBean was not injected.");
|
||||
return new MyFactoryBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class NonPublicParameterizedFactoryBeanInterfaceConfig {
|
||||
|
||||
@Autowired
|
||||
private DummyBean dummyBean;
|
||||
|
||||
@Bean
|
||||
FactoryBean<String> factoryBean() {
|
||||
Assert.notNull(dummyBean, "DummyBean was not injected.");
|
||||
return new MyFactoryBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class RawFactoryBeanInterfaceConfig {
|
||||
|
||||
@Autowired
|
||||
private DummyBean dummyBean;
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("rawtypes")
|
||||
public FactoryBean factoryBean() {
|
||||
Assert.notNull(dummyBean, "DummyBean was not injected.");
|
||||
return new MyFactoryBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class WildcardParameterizedFactoryBeanInterfaceConfig {
|
||||
|
||||
@Autowired
|
||||
private DummyBean dummyBean;
|
||||
|
||||
@Bean
|
||||
public FactoryBean<?> factoryBean() {
|
||||
Assert.notNull(dummyBean, "DummyBean was not injected.");
|
||||
return new MyFactoryBean();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+82
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,12 +16,18 @@
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import example.scannable.FooService;
|
||||
import example.scannable.ServiceInvocationCounter;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
@@ -32,38 +38,23 @@ import static org.junit.Assert.*;
|
||||
*/
|
||||
public class EnableAspectJAutoProxyTests {
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("example.scannable")
|
||||
@EnableAspectJAutoProxy
|
||||
static class Config_WithJDKProxy {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("example.scannable")
|
||||
@EnableAspectJAutoProxy(proxyTargetClass=true)
|
||||
static class Config_WithCGLIBProxy {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withJDKProxy() throws Exception {
|
||||
ApplicationContext ctx =
|
||||
new AnnotationConfigApplicationContext(Config_WithJDKProxy.class);
|
||||
public void withJdkProxy() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithJdkProxy.class);
|
||||
|
||||
aspectIsApplied(ctx);
|
||||
assertThat(AopUtils.isJdkDynamicProxy(ctx.getBean(FooService.class)), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withCGLIBProxy() throws Exception {
|
||||
ApplicationContext ctx =
|
||||
new AnnotationConfigApplicationContext(Config_WithCGLIBProxy.class);
|
||||
public void withCglibProxy() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithCglibProxy.class);
|
||||
|
||||
aspectIsApplied(ctx);
|
||||
assertThat(AopUtils.isCglibProxy(ctx.getBean(FooService.class)), is(true));
|
||||
}
|
||||
|
||||
|
||||
private void aspectIsApplied(ApplicationContext ctx) throws Exception {
|
||||
private void aspectIsApplied(ApplicationContext ctx) {
|
||||
FooService fooService = ctx.getBean(FooService.class);
|
||||
ServiceInvocationCounter counter = ctx.getBean(ServiceInvocationCounter.class);
|
||||
|
||||
@@ -79,4 +70,73 @@ public class EnableAspectJAutoProxyTests {
|
||||
fooService.foo(1);
|
||||
assertEquals(3, counter.getCount());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withAnnotationOnArgumentAndJdkProxy() {
|
||||
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(
|
||||
ConfigWithJdkProxy.class, SampleService.class, LoggingAspect.class);
|
||||
|
||||
SampleService sampleService = ctx.getBean(SampleService.class);
|
||||
sampleService.execute(new SampleDto());
|
||||
sampleService.execute(new SampleInputBean());
|
||||
sampleService.execute((SampleDto) null);
|
||||
sampleService.execute((SampleInputBean) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withAnnotationOnArgumentAndCglibProxy() {
|
||||
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(
|
||||
ConfigWithCglibProxy.class, SampleService.class, LoggingAspect.class);
|
||||
|
||||
SampleService sampleService = ctx.getBean(SampleService.class);
|
||||
sampleService.execute(new SampleDto());
|
||||
sampleService.execute(new SampleInputBean());
|
||||
sampleService.execute((SampleDto) null);
|
||||
sampleService.execute((SampleInputBean) null);
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("example.scannable")
|
||||
@EnableAspectJAutoProxy
|
||||
static class ConfigWithJdkProxy {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("example.scannable")
|
||||
@EnableAspectJAutoProxy(proxyTargetClass = true)
|
||||
static class ConfigWithCglibProxy {
|
||||
}
|
||||
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Loggable {
|
||||
}
|
||||
|
||||
@Loggable
|
||||
public static class SampleDto {
|
||||
}
|
||||
|
||||
public static class SampleInputBean {
|
||||
}
|
||||
|
||||
public static class SampleService {
|
||||
|
||||
// Not matched method on {@link LoggingAspect}.
|
||||
public void execute(SampleInputBean inputBean) {
|
||||
}
|
||||
|
||||
// Matched method on {@link LoggingAspect}
|
||||
public void execute(SampleDto dto) {
|
||||
}
|
||||
}
|
||||
|
||||
@Aspect
|
||||
public static class LoggingAspect {
|
||||
|
||||
@Before("@args(org.springframework.context.annotation.EnableAspectJAutoProxyTests.Loggable))")
|
||||
public void loggingBeginByAtArgs() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+62
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.context.annotation.configuration;
|
||||
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.After;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.junit.Test;
|
||||
@@ -23,9 +25,12 @@ import org.junit.Test;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
@@ -44,8 +49,20 @@ import static org.junit.Assert.*;
|
||||
* processing of the Aspect annotation.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class ConfigurationClassAspectIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void aspectAnnotatedConfiguration() {
|
||||
assertAdviceWasApplied(AspectConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurationIncludesAspect() {
|
||||
assertAdviceWasApplied(ConfigurationWithAspect.class);
|
||||
}
|
||||
|
||||
private void assertAdviceWasApplied(Class<?> configClass) {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(
|
||||
@@ -62,19 +79,17 @@ public class ConfigurationClassAspectIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aspectAnnotatedConfiguration() {
|
||||
assertAdviceWasApplied(AspectConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurationIncludesAspect() {
|
||||
assertAdviceWasApplied(ConfigurationWithAspect.class);
|
||||
public void withInnerClassAndLambdaExpression() {
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(Application.class, CountingAspect.class);
|
||||
ctx.getBeansOfType(Runnable.class).forEach((k, v) -> v.run());
|
||||
assertEquals(2, ctx.getBean(CountingAspect.class).count);
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
@Configuration
|
||||
static class AspectConfig {
|
||||
|
||||
@Bean
|
||||
public TestBean testBean() {
|
||||
return new TestBean("name");
|
||||
@@ -86,8 +101,10 @@ public class ConfigurationClassAspectIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class ConfigurationWithAspect {
|
||||
|
||||
@Bean
|
||||
public TestBean testBean() {
|
||||
return new TestBean("name");
|
||||
@@ -99,11 +116,48 @@ public class ConfigurationClassAspectIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
static class NameChangingAspect {
|
||||
|
||||
@Before("execution(* org.springframework.tests.sample.beans.TestBean.absquatulate(..)) && target(testBean)")
|
||||
public void touchBean(TestBean testBean) {
|
||||
testBean.setName("advisedName");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableAspectJAutoProxy
|
||||
public static class Application {
|
||||
|
||||
@Bean
|
||||
Runnable fromInnerClass() {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
Runnable fromLambdaExpression() {
|
||||
return () -> {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
public static class CountingAspect {
|
||||
|
||||
public int count = 0;
|
||||
|
||||
@After("execution(* java.lang.Runnable.*(..))")
|
||||
public void after(JoinPoint joinPoint) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="foo" class="java.lang.String">
|
||||
<constructor-arg value="hello"/>
|
||||
<qualifier value="foo" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
||||
+20
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,6 +28,7 @@ import java.util.Properties;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -48,6 +49,7 @@ import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.format.Formatter;
|
||||
import org.springframework.format.Printer;
|
||||
import org.springframework.format.annotation.NumberFormat;
|
||||
import org.springframework.format.datetime.joda.DateTimeParser;
|
||||
import org.springframework.format.datetime.joda.JodaDateTimeFormatAnnotationFormatterFactory;
|
||||
import org.springframework.format.datetime.joda.ReadablePartialPrinter;
|
||||
@@ -58,6 +60,8 @@ import static org.junit.Assert.*;
|
||||
/**
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
* @author Kazuki Shimizu
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public class FormattingConversionServiceTests {
|
||||
|
||||
@@ -101,6 +105,7 @@ public class FormattingConversionServiceTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
public void testFormatFieldForValueInjection() {
|
||||
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
|
||||
ac.registerBeanDefinition("valueBean", new RootBeanDefinition(ValueBean.class));
|
||||
@@ -111,6 +116,7 @@ public class FormattingConversionServiceTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
public void testFormatFieldForValueInjectionUsingMetaAnnotations() {
|
||||
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(MetaValueBean.class);
|
||||
@@ -120,12 +126,15 @@ public class FormattingConversionServiceTests {
|
||||
ac.registerBeanDefinition("ppc", new RootBeanDefinition(PropertyPlaceholderConfigurer.class));
|
||||
ac.refresh();
|
||||
System.setProperty("myDate", "10-31-09");
|
||||
System.setProperty("myNumber", "99.99%");
|
||||
try {
|
||||
MetaValueBean valueBean = ac.getBean(MetaValueBean.class);
|
||||
assertEquals(new LocalDate(2009, 10, 31), new LocalDate(valueBean.date));
|
||||
assertEquals(Double.valueOf(0.9999), valueBean.number);
|
||||
}
|
||||
finally {
|
||||
System.clearProperty("myDate");
|
||||
System.clearProperty("myNumber");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +151,7 @@ public class FormattingConversionServiceTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
public void testFormatFieldForAnnotationWithPlaceholders() throws Exception {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
@@ -157,6 +167,7 @@ public class FormattingConversionServiceTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
public void testFormatFieldForAnnotationWithPlaceholdersAndFactoryBean() throws Exception {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
@@ -336,13 +347,14 @@ public class FormattingConversionServiceTests {
|
||||
public Date date;
|
||||
}
|
||||
|
||||
|
||||
public static class MetaValueBean {
|
||||
|
||||
@MyDateAnn
|
||||
public Date date;
|
||||
}
|
||||
|
||||
@MyNumberAnn
|
||||
public Double number;
|
||||
}
|
||||
|
||||
@Value("${myDate}")
|
||||
@org.springframework.format.annotation.DateTimeFormat(pattern="MM-d-yy")
|
||||
@@ -350,6 +362,11 @@ public class FormattingConversionServiceTests {
|
||||
public static @interface MyDateAnn {
|
||||
}
|
||||
|
||||
@Value("${myNumber}")
|
||||
@NumberFormat(style = NumberFormat.Style.PERCENT)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public static @interface MyNumberAnn {
|
||||
}
|
||||
|
||||
public static class Model {
|
||||
|
||||
@@ -368,7 +385,6 @@ public class FormattingConversionServiceTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ModelWithPlaceholders {
|
||||
|
||||
@org.springframework.format.annotation.DateTimeFormat(style="${dateStyle}")
|
||||
@@ -386,13 +402,11 @@ public class FormattingConversionServiceTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@org.springframework.format.annotation.DateTimeFormat(pattern="${datePattern}")
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public static @interface MyDatePattern {
|
||||
}
|
||||
|
||||
|
||||
public static class NullReturningFormatter implements Formatter<Integer> {
|
||||
|
||||
@Override
|
||||
@@ -407,12 +421,10 @@ public class FormattingConversionServiceTests {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class MyDate extends Date {
|
||||
}
|
||||
|
||||
|
||||
private static class ModelWithSubclassField {
|
||||
|
||||
@org.springframework.format.annotation.DateTimeFormat(style = "S-")
|
||||
|
||||
+28
-4
@@ -17,6 +17,8 @@
|
||||
package org.springframework.jmx.export;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -643,6 +645,28 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
ObjectNameManager.getInstance(objectName2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnoreBeanName() throws MalformedObjectNameException {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
String firstBeanName = "spring:type=TestBean";
|
||||
factory.registerSingleton(firstBeanName, new TestBean("test"));
|
||||
String secondBeanName = "spring:type=TestBean2";
|
||||
factory.registerSingleton(secondBeanName, new TestBean("test2"));
|
||||
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setServer(getServer());
|
||||
exporter.setAssembler(new NamedBeanAutodetectCapableMBeanInfoAssemblerStub(firstBeanName, secondBeanName));
|
||||
exporter.setBeanFactory(factory);
|
||||
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL);
|
||||
exporter.addExcludedBean(secondBeanName);
|
||||
|
||||
start(exporter);
|
||||
assertIsRegistered("Bean not autodetected in (AUTODETECT_ALL) mode",
|
||||
ObjectNameManager.getInstance(firstBeanName));
|
||||
assertIsNotRegistered("Bean should have been excluded",
|
||||
ObjectNameManager.getInstance(secondBeanName));
|
||||
}
|
||||
|
||||
private ConfigurableApplicationContext load(String context) {
|
||||
return new ClassPathXmlApplicationContext(context, getClass());
|
||||
}
|
||||
@@ -763,15 +787,15 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
private static final class NamedBeanAutodetectCapableMBeanInfoAssemblerStub extends
|
||||
SimpleReflectiveMBeanInfoAssembler implements AutodetectCapableMBeanInfoAssembler {
|
||||
|
||||
private String namedBean;
|
||||
private Collection<String> namedBeans;
|
||||
|
||||
public NamedBeanAutodetectCapableMBeanInfoAssemblerStub(String namedBean) {
|
||||
this.namedBean = namedBean;
|
||||
public NamedBeanAutodetectCapableMBeanInfoAssemblerStub(String... namedBeans) {
|
||||
this.namedBeans = Arrays.asList(namedBeans);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeBean(Class<?> beanClass, String beanName) {
|
||||
return this.namedBean.equals(beanName);
|
||||
return this.namedBeans.contains(beanName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+64
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,15 +25,20 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.GenericXmlApplicationContext;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@@ -106,10 +111,32 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
||||
|
||||
@Test
|
||||
public void handleExceptionWithFuture() {
|
||||
ConfigurableApplicationContext context = initContext(
|
||||
new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class));
|
||||
ConfigurableApplicationContext context =
|
||||
new AnnotationConfigApplicationContext(ConfigWithExceptionHandler.class);
|
||||
ITestBean testBean = context.getBean("target", ITestBean.class);
|
||||
final Future<Object> result = testBean.failWithFuture();
|
||||
|
||||
TestableAsyncUncaughtExceptionHandler exceptionHandler =
|
||||
context.getBean("exceptionHandler", TestableAsyncUncaughtExceptionHandler.class);
|
||||
assertFalse("handler should not have been called yet", exceptionHandler.isCalled());
|
||||
Future<Object> result = testBean.failWithFuture();
|
||||
assertFutureWithException(result, exceptionHandler);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleExceptionWithListenableFuture() {
|
||||
ConfigurableApplicationContext context =
|
||||
new AnnotationConfigApplicationContext(ConfigWithExceptionHandler.class);
|
||||
ITestBean testBean = context.getBean("target", ITestBean.class);
|
||||
|
||||
TestableAsyncUncaughtExceptionHandler exceptionHandler =
|
||||
context.getBean("exceptionHandler", TestableAsyncUncaughtExceptionHandler.class);
|
||||
assertFalse("handler should not have been called yet", exceptionHandler.isCalled());
|
||||
Future<Object> result = testBean.failWithListenableFuture();
|
||||
assertFutureWithException(result, exceptionHandler);
|
||||
}
|
||||
|
||||
private void assertFutureWithException(Future<Object> result,
|
||||
TestableAsyncUncaughtExceptionHandler exceptionHandler) {
|
||||
|
||||
try {
|
||||
result.get();
|
||||
@@ -121,6 +148,7 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
||||
// expected
|
||||
assertEquals("Wrong exception cause", UnsupportedOperationException.class, ex.getCause().getClass());
|
||||
}
|
||||
assertFalse("handler should never be called with Future return type", exceptionHandler.isCalled());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -173,7 +201,7 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
|
||||
private static interface ITestBean {
|
||||
private interface ITestBean {
|
||||
|
||||
Thread getThread();
|
||||
|
||||
@@ -181,6 +209,8 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
||||
|
||||
Future<Object> failWithFuture();
|
||||
|
||||
ListenableFuture<Object> failWithListenableFuture();
|
||||
|
||||
void failWithVoid();
|
||||
|
||||
void await(long timeout);
|
||||
@@ -206,11 +236,19 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public Future<Object> failWithFuture() {
|
||||
throw new UnsupportedOperationException("failWithFuture");
|
||||
}
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public ListenableFuture<Object> failWithListenableFuture() {
|
||||
throw new UnsupportedOperationException("failWithListenableFuture");
|
||||
}
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void failWithVoid() {
|
||||
throw new UnsupportedOperationException("failWithVoid");
|
||||
}
|
||||
@@ -234,4 +272,25 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
static class ConfigWithExceptionHandler extends AsyncConfigurerSupport {
|
||||
|
||||
@Bean
|
||||
public ITestBean target() {
|
||||
return new TestBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
|
||||
return exceptionHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestableAsyncUncaughtExceptionHandler exceptionHandler() {
|
||||
return new TestableAsyncUncaughtExceptionHandler();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -48,21 +48,23 @@ public class ExecutorBeanDefinitionParserTests {
|
||||
"executorContext.xml", ExecutorBeanDefinitionParserTests.class);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void defaultExecutor() throws Exception {
|
||||
Object executor = this.context.getBean("default");
|
||||
ThreadPoolTaskExecutor executor = this.context.getBean("default", ThreadPoolTaskExecutor.class);
|
||||
assertEquals(1, getCorePoolSize(executor));
|
||||
assertEquals(Integer.MAX_VALUE, getMaxPoolSize(executor));
|
||||
assertEquals(Integer.MAX_VALUE, getQueueCapacity(executor));
|
||||
assertEquals(60, getKeepAliveSeconds(executor));
|
||||
assertEquals(false, getAllowCoreThreadTimeOut(executor));
|
||||
|
||||
FutureTask<String> task = new FutureTask<String>(new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return "foo";
|
||||
}
|
||||
});
|
||||
((ThreadPoolTaskExecutor)executor).execute(task);
|
||||
executor.execute(task);
|
||||
assertEquals("foo", task.get());
|
||||
}
|
||||
|
||||
|
||||
+11
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,4 +46,14 @@ public class CronSequenceGeneratorTests {
|
||||
new CronSequenceGenerator("0 */2 1-4 * * *").next(new Date(2012, 6, 1, 9, 0)));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWith0Increment() {
|
||||
new CronSequenceGenerator("*/0 * * * * *").next(new Date(2012, 6, 1, 9, 0));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWithNegativeIncrement() {
|
||||
new CronSequenceGenerator("*/-1 * * * * *").next(new Date(2012, 6, 1, 9, 0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2706,11 +2706,13 @@ class MethodWriter extends MethodVisitor {
|
||||
l = l.successor;
|
||||
}
|
||||
// Update the offsets in the uninitialized types
|
||||
for (i = 0; i < cw.typeTable.length; ++i) {
|
||||
Item item = cw.typeTable[i];
|
||||
if (item != null && item.type == ClassWriter.TYPE_UNINIT) {
|
||||
item.intVal = getNewOffset(allIndexes, allSizes, 0,
|
||||
item.intVal);
|
||||
if (cw.typeTable != null) {
|
||||
for (i = 0; i < cw.typeTable.length; ++i) {
|
||||
Item item = cw.typeTable[i];
|
||||
if (item != null && item.type == ClassWriter.TYPE_UNINIT) {
|
||||
item.intVal = getNewOffset(allIndexes, allSizes, 0,
|
||||
item.intVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
// The stack map frames are not serialized yet, so we don't need
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -309,6 +309,7 @@ public class MethodParameter {
|
||||
/**
|
||||
* Return the generic type of the method/constructor parameter.
|
||||
* @return the parameter type (never {@code null})
|
||||
* @since 3.0
|
||||
*/
|
||||
public Type getGenericParameterType() {
|
||||
if (this.genericParameterType == null) {
|
||||
@@ -324,6 +325,12 @@ public class MethodParameter {
|
||||
return this.genericParameterType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the nested type of the method/constructor parameter.
|
||||
* @return the parameter type (never {@code null})
|
||||
* @see #getNestingLevel()
|
||||
* @since 3.1
|
||||
*/
|
||||
public Class<?> getNestedParameterType() {
|
||||
if (this.nestingLevel > 1) {
|
||||
Type type = getGenericParameterType();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user