mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
193 Commits
v6.2.7
...
v4.3.3.RELEASE
| Author | SHA1 | Date | |
|---|---|---|---|
| 90718ef0d9 | |||
| 81f6c22e51 | |||
| 78a8245f4a | |||
| 049861afb4 | |||
| 3df7083f69 | |||
| ca17edd5ac | |||
| c26bf871b7 | |||
| 15d3e8c3e1 | |||
| 66b370e103 | |||
| 2bbfbb1d50 | |||
| ace25d4987 | |||
| 59cb9a4e60 | |||
| 0dce570157 | |||
| 7ddaf49eb2 | |||
| e947363a11 | |||
| 5dbfe48d24 | |||
| 07d5f8b123 | |||
| be99603f1b | |||
| 54db496815 | |||
| fbe7ddb640 | |||
| 55c37d2a57 | |||
| 4b445531f5 | |||
| 12afc263a4 | |||
| 040d131284 | |||
| 73bbe0849a | |||
| 09a0615df0 | |||
| 669d5815c9 | |||
| bd24b97bd3 | |||
| db196ce5d8 | |||
| 4396b211ce | |||
| 367949e914 | |||
| ae2bbe7f19 | |||
| 819e14f91b | |||
| fcf3ccba98 | |||
| 558a10b54f | |||
| 43c60a02f7 | |||
| 6501bc5d32 | |||
| f3dae0c9ad | |||
| dc2cafc888 | |||
| 49fc4923be | |||
| efb5f17a60 | |||
| 086e764845 | |||
| c30290b43c | |||
| d26421fe3b | |||
| 37670924f6 | |||
| ee5143b54b | |||
| acbb2544bf | |||
| d8f7347000 | |||
| 3b91dec462 | |||
| 05f74b4218 | |||
| 8e98177fb3 | |||
| 815a3ad0de | |||
| 5075dd4dfa | |||
| ca09dcbe89 | |||
| 198a74d793 | |||
| fe404628e9 | |||
| 5a004c3b2a | |||
| 430180aa96 | |||
| e828be96f0 | |||
| 52447efb97 | |||
| d09b0fe83a | |||
| 798d8668a4 | |||
| 2a82b8fed9 | |||
| 696f687419 | |||
| 9b91b9db8c | |||
| 026473280b | |||
| a7849b2861 | |||
| 74bf659c56 | |||
| c2feedb7a2 | |||
| 0735e9ba98 | |||
| ab686732d0 | |||
| 6d86437369 | |||
| 184285ab27 | |||
| 1e8065d040 | |||
| f735d12247 | |||
| 7135bc2dc2 | |||
| 9044706796 | |||
| 5f68da3153 | |||
| 5222489a01 | |||
| 27f830f345 | |||
| 8d7db8e450 | |||
| da56758054 | |||
| 66dcc4b6db | |||
| 6eab5622c7 | |||
| af53f3d6cf | |||
| 188e5327ee | |||
| 1932a9d729 | |||
| c926ec477a | |||
| 7b11fa18a1 | |||
| e6cefdca25 | |||
| fbeff475b3 | |||
| d057099c17 | |||
| 411700d7e6 | |||
| b4e9d918f2 | |||
| 2756c364d2 | |||
| 43faabd4cc | |||
| a4a71a8904 | |||
| e23ac031ff | |||
| 79a56967a1 | |||
| 0bc0453700 | |||
| 35e247aa26 | |||
| 67ba187b6f | |||
| 67f0b1986c | |||
| 60e0177d00 | |||
| 4543a28e51 | |||
| aade2d1ec9 | |||
| 4627545a3b | |||
| e2ba7c9b8c | |||
| 6f5596ac5c | |||
| 7d1c2f191a | |||
| 4ada571384 | |||
| ad8ebbaa05 | |||
| 4854989db4 | |||
| 7c5050cf80 | |||
| 14ae8be547 | |||
| ff878ea9dc | |||
| 7021a4be44 | |||
| 5c4737c3d0 | |||
| fbf3807af1 | |||
| 703c37ec88 | |||
| 96440878bb | |||
| b5c11ffb1c | |||
| 7f5b323d50 | |||
| 67176e2b75 | |||
| 79f3cf3263 | |||
| 9ee1dc79fd | |||
| 9e2c34dfa6 | |||
| cc93c2a559 | |||
| 15c7044c4d | |||
| 0ef80d3579 | |||
| 95c2e0a996 | |||
| da3e8611e1 | |||
| 64595597f3 | |||
| 82f2983cd4 | |||
| 9451177c35 | |||
| 9ed087d5da | |||
| 77f22e9674 | |||
| 8ccfdbbcf9 | |||
| 5a92aa4e06 | |||
| 7b1010cf61 | |||
| 45b2f5bac4 | |||
| 36e1c82ef5 | |||
| 503d65d570 | |||
| fe17f8da41 | |||
| b583aa1579 | |||
| e0d81b97bb | |||
| 90752f9d87 | |||
| 3663aa675a | |||
| 1ca4b81856 | |||
| 4e7e06f549 | |||
| b2f0bdb0f4 | |||
| d98bd34200 | |||
| 940bdd878e | |||
| df556333a8 | |||
| 116f05eda6 | |||
| b187bbeca3 | |||
| 479a83b628 | |||
| 1c18100143 | |||
| 5d3c0f33f6 | |||
| afe106e254 | |||
| 69dd40ec89 | |||
| dee50d5e28 | |||
| 9e93403857 | |||
| 12bff6b3a0 | |||
| 70e666b4a3 | |||
| 29f980ec72 | |||
| 1d39d762f0 | |||
| 4d6d5e0ddd | |||
| 4ea5f070a4 | |||
| da59b4da9b | |||
| 0065a160cc | |||
| 52f46c7fea | |||
| f0a826ec0c | |||
| 5c3c0f73c1 | |||
| be0b71ce31 | |||
| f85d48dd31 | |||
| a1b58ee601 | |||
| e30429051d | |||
| 942ead75e2 | |||
| 453688f6df | |||
| 7d7a161102 | |||
| aaa223ae66 | |||
| d11c624fb0 | |||
| 275e51b19d | |||
| ab62edeeaa | |||
| 813108a928 | |||
| 3c14911401 | |||
| 4337f14627 | |||
| 92d78c10a2 | |||
| 16d5ba9b3a | |||
| 52065a736b | |||
| 11cb109114 | |||
| d7eadd41d6 |
+4
-5
@@ -88,15 +88,14 @@ present in the framework.
|
||||
1. Preserve existing formatting; i.e. do not reformat code for its own sake
|
||||
1. Search the codebase using `git grep` and other tools to discover common
|
||||
naming conventions, etc.
|
||||
1. Latin-1 (ISO-8859-1) encoding for Java sources; use `native2ascii` to convert
|
||||
if necessary
|
||||
1. UTF-8 encoding for Java sources
|
||||
|
||||
|
||||
### Add Apache license header to all new classes
|
||||
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -124,11 +123,11 @@ modified a file in 2015 whose header still reads:
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
```
|
||||
|
||||
Then be sure to update it to 2015 accordingly:
|
||||
Then be sure to update it to 2016 accordingly:
|
||||
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
```
|
||||
|
||||
### Use @since tags for newly-added public API types and methods
|
||||
|
||||
+26
-33
@@ -32,11 +32,11 @@ configure(allprojects) { project ->
|
||||
version = qualifyVersionIfNecessary(version)
|
||||
|
||||
ext.aspectjVersion = "1.8.9"
|
||||
ext.caffeineVersion = "2.3.1"
|
||||
ext.caffeineVersion = "2.3.3"
|
||||
ext.eclipselinkVersion = "2.4.2"
|
||||
ext.ehcacheVersion = "2.10.2"
|
||||
ext.ehcachejcacheVersion = "1.0.1"
|
||||
ext.ehcache3Version = "3.1.0"
|
||||
ext.ehcache3Version = "3.1.2"
|
||||
ext.ejbVersion = "3.0"
|
||||
ext.fileuploadVersion = "1.3.2"
|
||||
ext.freemarkerVersion = "2.3.23"
|
||||
@@ -46,37 +46,37 @@ configure(allprojects) { project ->
|
||||
ext.hamcrestVersion = "1.3"
|
||||
ext.hibernate3Version = "3.6.10.Final"
|
||||
ext.hibernate4Version = "4.3.11.Final"
|
||||
ext.hibernate5Version = "5.2.1.Final"
|
||||
ext.hibernate5Version = "5.2.2.Final"
|
||||
ext.hibval4Version = "4.3.2.Final"
|
||||
ext.hibval5Version = "5.2.4.Final"
|
||||
ext.hsqldbVersion = "2.3.4"
|
||||
ext.httpasyncVersion = "4.1.2"
|
||||
ext.httpclientVersion = "4.5.2"
|
||||
ext.jackson2Version = "2.8.0.rc2"
|
||||
ext.jackson2Version = "2.8.2"
|
||||
ext.jasperreportsVersion = "6.2.1" // our tests fail with JR-internal NPEs against 6.2.2 and higher
|
||||
ext.javamailVersion = "1.5.5"
|
||||
ext.jettyVersion = "9.3.10.v20160621"
|
||||
ext.jettyVersion = "9.3.11.v20160721"
|
||||
ext.jodaVersion = "2.9.4"
|
||||
ext.jrubyVersion = "1.7.25" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory)
|
||||
ext.jtaVersion = "1.2"
|
||||
ext.junitVersion = "4.12"
|
||||
ext.log4jVersion = "1.2.17"
|
||||
ext.nettyVersion = "4.1.1.Final"
|
||||
ext.nettyVersion = "4.1.5.Final"
|
||||
ext.okhttpVersion = "2.7.5"
|
||||
ext.okhttp3Version = "3.3.1"
|
||||
ext.okhttp3Version = "3.4.1"
|
||||
ext.openjpaVersion = "2.4.1"
|
||||
ext.poiVersion = "3.14"
|
||||
ext.reactorVersion = "2.0.8.RELEASE"
|
||||
ext.romeVersion = "1.6.0"
|
||||
ext.romeVersion = "1.7.0"
|
||||
ext.slf4jVersion = "1.7.21"
|
||||
ext.snakeyamlVersion = "1.17"
|
||||
ext.snifferVersion = "1.15"
|
||||
ext.testngVersion = "6.9.10"
|
||||
ext.tiles2Version = "2.2.2"
|
||||
ext.tiles3Version = "3.0.5"
|
||||
ext.tomcatVersion = "8.5.3"
|
||||
ext.tomcatVersion = "8.5.5"
|
||||
ext.tyrusVersion = "1.3.5" // constrained by WebLogic 12.1.3 support
|
||||
ext.undertowVersion = "1.4.0.CR2"
|
||||
ext.undertowVersion = "1.3.24.Final"
|
||||
ext.xmlunitVersion = "1.6"
|
||||
ext.xstreamVersion = "1.4.9"
|
||||
|
||||
@@ -110,11 +110,13 @@ configure(allprojects) { project ->
|
||||
compileJava {
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
compileTestJava {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
options.encoding = 'UTF-8'
|
||||
options.compilerArgs += "-parameters"
|
||||
}
|
||||
|
||||
@@ -199,10 +201,10 @@ configure(allprojects) { project ->
|
||||
"http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
|
||||
"http://ehcache.org/apidocs/${ehcacheVersion}",
|
||||
"http://ehcache.org/apidocs/${ehcache3Version}",
|
||||
"http://quartz-scheduler.org/api/2.2.0/",
|
||||
"http://fasterxml.github.io/jackson-core/javadoc/2.7/",
|
||||
"http://fasterxml.github.io/jackson-databind/javadoc/2.7/",
|
||||
"http://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.7/",
|
||||
"http://quartz-scheduler.org/api/2.2.1/",
|
||||
"http://fasterxml.github.io/jackson-core/javadoc/2.8/",
|
||||
"http://fasterxml.github.io/jackson-databind/javadoc/2.8/",
|
||||
"http://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.8/",
|
||||
"http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/"
|
||||
] as String[]
|
||||
}
|
||||
@@ -355,7 +357,7 @@ project("spring-core") {
|
||||
optional("log4j:log4j:${log4jVersion}")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
|
||||
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
|
||||
testCompile("com.fasterxml.woodstox:woodstox-core:5.0.2") {
|
||||
testCompile("com.fasterxml.woodstox:woodstox-core:5.0.3") {
|
||||
exclude group: "stax", module: "stax-api"
|
||||
}
|
||||
}
|
||||
@@ -477,7 +479,7 @@ project("spring-context") {
|
||||
optional("javax.inject:javax.inject:1")
|
||||
optional("javax.ejb:ejb-api:${ejbVersion}")
|
||||
optional("javax.enterprise.concurrent:javax.enterprise.concurrent-api:1.0")
|
||||
optional("javax.money:money-api:1.0")
|
||||
optional("javax.money:money-api:1.0.1")
|
||||
optional("org.eclipse.persistence:javax.persistence:2.0.0")
|
||||
optional("javax.validation:validation-api:1.0.0.GA")
|
||||
optional("org.hibernate:hibernate-validator:${hibval4Version}")
|
||||
@@ -556,13 +558,6 @@ project("spring-oxm") {
|
||||
description = "Spring Object/XML Marshalling"
|
||||
apply from: "oxm.gradle"
|
||||
|
||||
compileTestJava {
|
||||
// necessary to avoid java.lang.VerifyError on jibx compilation
|
||||
// see http://jira.codehaus.org/browse/JIBX-465
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-core"))
|
||||
@@ -581,14 +576,12 @@ project("spring-oxm") {
|
||||
testCompile(project(":spring-context"))
|
||||
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
|
||||
testCompile("xpp3:xpp3:1.1.4c")
|
||||
testCompile("org.codehaus.jettison:jettison:1.3.7") {
|
||||
testCompile("org.codehaus.jettison:jettison:1.3.8") {
|
||||
exclude group: 'stax', module: 'stax-api'
|
||||
}
|
||||
if (compileTestJava.enabled) {
|
||||
testCompile(files(genCastor.classesDir).builtBy(genCastor))
|
||||
testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
|
||||
testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans))
|
||||
}
|
||||
testCompile(files(genCastor.classesDir).builtBy(genCastor))
|
||||
testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
|
||||
testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -879,10 +872,10 @@ project("spring-webmvc") {
|
||||
testCompile("commons-io:commons-io:1.3")
|
||||
testCompile("joda-time:joda-time:${jodaVersion}")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
testCompile("org.jruby:jruby:${jrubyVersion}")
|
||||
testCompile("org.python:jython-standalone:2.5.3")
|
||||
testCompile("org.mozilla:rhino:1.7.7.1")
|
||||
testCompile("org.webjars:underscorejs:1.8.3")
|
||||
testRuntime("org.jruby:jruby:${jrubyVersion}")
|
||||
testRuntime("org.python:jython-standalone:2.5.3")
|
||||
testRuntime("org.webjars:underscorejs:1.8.3")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1367,7 +1360,7 @@ configure(rootProject) {
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
description = "Generates gradlew[.bat] scripts"
|
||||
gradleVersion = "2.13"
|
||||
gradleVersion = "2.14.1"
|
||||
|
||||
doLast() {
|
||||
def gradleOpts = "-XX:MaxMetaspaceSize=1024m -Xmx1024m"
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=4.3.1.BUILD-SNAPSHOT
|
||||
version=4.3.3.RELEASE
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+2
-2
@@ -1,6 +1,6 @@
|
||||
#Wed Jun 15 12:59:30 CEST 2016
|
||||
#Wed Aug 17 21:21:18 CEST 2016
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip
|
||||
|
||||
@@ -46,7 +46,7 @@ public interface MethodInterceptor extends Interceptor {
|
||||
* after the invocation. Polite implementations would certainly
|
||||
* like to invoke {@link Joinpoint#proceed()}.
|
||||
* @param invocation the method invocation joinpoint
|
||||
* @return the result of the call to {@link Joinpoint#proceed();
|
||||
* @return the result of the call to {@link Joinpoint#proceed()};
|
||||
* might be intercepted by the interceptor
|
||||
* @throws Throwable if the interceptors or the target object
|
||||
* throws an exception
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -55,10 +55,12 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
return this.aspectClass.newInstance();
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new AopConfigException("Unable to instantiate aspect class [" + this.aspectClass.getName() + "]", ex);
|
||||
throw new AopConfigException(
|
||||
"Unable to instantiate aspect class: " + this.aspectClass.getName(), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new AopConfigException("Cannot access element class [" + this.aspectClass.getName() + "]", ex);
|
||||
throw new AopConfigException(
|
||||
"Could not access aspect constructor: " + this.aspectClass.getName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -139,7 +139,8 @@ public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanC
|
||||
* @return whether the given interface is an internal language interface
|
||||
*/
|
||||
protected boolean isInternalLanguageInterface(Class<?> ifc) {
|
||||
return ifc.getName().equals("groovy.lang.GroovyObject");
|
||||
return (ifc.getName().equals("groovy.lang.GroovyObject") ||
|
||||
ifc.getName().endsWith(".cglib.proxy.Factory"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-13
@@ -1,6 +1,5 @@
|
||||
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,27 +28,21 @@ public class NopInterceptor implements MethodInterceptor {
|
||||
|
||||
private int count;
|
||||
|
||||
/**
|
||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(MethodInvocation)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
increment();
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
protected void increment() {
|
||||
this.count++;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
protected void increment() {
|
||||
++count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
@@ -62,5 +55,9 @@ public class NopInterceptor implements MethodInterceptor {
|
||||
return this.count == ((NopInterceptor) other).count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return NopInterceptor.class.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,22 +28,10 @@ import org.springframework.util.ObjectUtils;
|
||||
@SuppressWarnings("serial")
|
||||
public class SerializablePerson implements Person, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
@Override
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@@ -55,6 +43,16 @@ public class SerializablePerson implements Person, Serializable {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object echo(Object o) throws Throwable {
|
||||
if (o instanceof Throwable) {
|
||||
@@ -63,10 +61,6 @@ public class SerializablePerson implements Person, Serializable {
|
||||
return o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
@@ -77,4 +71,9 @@ public class SerializablePerson implements Person, Serializable {
|
||||
return p.age == age && ObjectUtils.nullSafeEquals(name, p.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return SerializablePerson.class.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
@@ -36,7 +36,9 @@ import org.springframework.util.ObjectUtils;
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @author Sam Brannen
|
||||
* @deprecated as of Spring 4.3, in favor of a custom aspect for such purposes
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMethod()) {
|
||||
|
||||
private final Expectations expectations = new Expectations();
|
||||
|
||||
+2
@@ -59,7 +59,9 @@ import org.aspectj.lang.annotation.SuppressAjWarnings;
|
||||
* @author Ramnivas Laddad
|
||||
* @author Sam Brannen
|
||||
* @see MockStaticEntityMethods
|
||||
* @deprecated as of Spring 4.3, in favor of a custom aspect for such purposes
|
||||
*/
|
||||
@Deprecated
|
||||
@RequiredTypes("javax.persistence.Entity")
|
||||
public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodMockingControl {
|
||||
|
||||
|
||||
+2
@@ -29,7 +29,9 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Sam Brannen
|
||||
* @deprecated as of Spring 4.3, in favor of a custom aspect for such purposes
|
||||
*/
|
||||
@Deprecated
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface MockStaticEntityMethods {
|
||||
|
||||
+4
-6
@@ -94,7 +94,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
|
||||
private String nestedPath = "";
|
||||
|
||||
private Object rootObject;
|
||||
Object rootObject;
|
||||
|
||||
/**
|
||||
* Map with cached nested Accessors: nested path -> Accessor instance.
|
||||
@@ -590,7 +590,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
|
||||
throw new ConversionNotSupportedException(pce, requiredType, ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
catch (IllegalArgumentException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
|
||||
throw new TypeMismatchException(pce, requiredType, ex);
|
||||
@@ -914,11 +914,9 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
return BeanUtils.instantiate(type);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// TODO: Root cause exception context is lost here; just exception message preserved.
|
||||
// Should we throw another exception type that preserves context instead?
|
||||
catch (Throwable ex) {
|
||||
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + name,
|
||||
"Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path: " + ex);
|
||||
"Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ public abstract class AbstractPropertyAccessor extends TypeConverterSupport impl
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyAccessException if the property was valid but the
|
||||
* accessor method failed or a type mismatch occured
|
||||
* accessor method failed or a type mismatch occurred
|
||||
*/
|
||||
@Override
|
||||
public abstract void setPropertyValue(String propertyName, Object value) throws BeansException;
|
||||
|
||||
@@ -63,11 +63,10 @@ public abstract class BeanUtils {
|
||||
|
||||
/**
|
||||
* Convenience method to instantiate a class using its no-arg constructor.
|
||||
* As this method doesn't try to load classes by name, it should avoid
|
||||
* class-loading issues.
|
||||
* @param clazz class to instantiate
|
||||
* @return the new instance
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated
|
||||
* @see Class#newInstance()
|
||||
*/
|
||||
public static <T> T instantiate(Class<T> clazz) throws BeanInstantiationException {
|
||||
Assert.notNull(clazz, "Class must not be null");
|
||||
@@ -87,13 +86,12 @@ public abstract class BeanUtils {
|
||||
|
||||
/**
|
||||
* Instantiate a class using its no-arg constructor.
|
||||
* As this method doesn't try to load classes by name, it should avoid
|
||||
* class-loading issues.
|
||||
* <p>Note that this method tries to set the constructor accessible
|
||||
* if given a non-accessible (that is, non-public) constructor.
|
||||
* @param clazz class to instantiate
|
||||
* @return the new instance
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated
|
||||
* @see Constructor#newInstance
|
||||
*/
|
||||
public static <T> T instantiateClass(Class<T> clazz) throws BeanInstantiationException {
|
||||
Assert.notNull(clazz, "Class must not be null");
|
||||
@@ -111,17 +109,15 @@ public abstract class BeanUtils {
|
||||
/**
|
||||
* Instantiate a class using its no-arg constructor and return the new instance
|
||||
* as the specified assignable type.
|
||||
* <p>Useful in cases where
|
||||
* the type of the class to instantiate (clazz) is not available, but the type
|
||||
* desired (assignableTo) is known.
|
||||
* <p>As this method doesn't try to load classes by name, it should avoid
|
||||
* class-loading issues.
|
||||
* <p>Note that this method tries to set the constructor accessible
|
||||
* if given a non-accessible (that is, non-public) constructor.
|
||||
* <p>Useful in cases where the type of the class to instantiate (clazz) is not
|
||||
* available, but the type desired (assignableTo) is known.
|
||||
* <p>Note that this method tries to set the constructor accessible if given a
|
||||
* non-accessible (that is, non-public) constructor.
|
||||
* @param clazz class to instantiate
|
||||
* @param assignableTo type that clazz must be assignableTo
|
||||
* @return the new instance
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated
|
||||
* @see Constructor#newInstance
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T instantiateClass(Class<?> clazz, Class<T> assignableTo) throws BeanInstantiationException {
|
||||
@@ -131,14 +127,13 @@ public abstract class BeanUtils {
|
||||
|
||||
/**
|
||||
* Convenience method to instantiate a class using the given constructor.
|
||||
* As this method doesn't try to load classes by name, it should avoid
|
||||
* class-loading issues.
|
||||
* <p>Note that this method tries to set the constructor accessible
|
||||
* if given a non-accessible (that is, non-public) constructor.
|
||||
* <p>Note that this method tries to set the constructor accessible if given a
|
||||
* non-accessible (that is, non-public) constructor.
|
||||
* @param ctor the constructor to instantiate
|
||||
* @param args the constructor arguments to apply
|
||||
* @return the new instance
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated
|
||||
* @see Constructor#newInstance
|
||||
*/
|
||||
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
|
||||
Assert.notNull(ctor, "Constructor must not be null");
|
||||
|
||||
@@ -141,6 +141,7 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
*/
|
||||
public void setBeanInstance(Object object) {
|
||||
this.wrappedObject = object;
|
||||
this.rootObject = object;
|
||||
this.typeConverterDelegate = new TypeConverterDelegate(this, this.wrappedObject);
|
||||
setIntrospectionClass(object.getClass());
|
||||
}
|
||||
|
||||
+14
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,6 +24,7 @@ package org.springframework.beans;
|
||||
* spouse property of the target object has a null value.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class NullValueInNestedPathException extends InvalidPropertyException {
|
||||
@@ -47,4 +48,16 @@ public class NullValueInNestedPathException extends InvalidPropertyException {
|
||||
super(beanClass, propertyName, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new NullValueInNestedPathException.
|
||||
* @param beanClass the offending bean class
|
||||
* @param propertyName the offending property
|
||||
* @param msg the detail message
|
||||
* @param cause the root cause
|
||||
* @since 4.3.2
|
||||
*/
|
||||
public NullValueInNestedPathException(Class<?> beanClass, String propertyName, String msg, Throwable cause) {
|
||||
super(beanClass, propertyName, msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -120,7 +120,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyAccessException if the property was valid but the
|
||||
* accessor method failed or a type mismatch occured
|
||||
* accessor method failed or a type mismatch occurred
|
||||
*/
|
||||
void setPropertyValue(String propertyName, Object value) throws BeansException;
|
||||
|
||||
@@ -130,7 +130,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyAccessException if the property was valid but the
|
||||
* accessor method failed or a type mismatch occured
|
||||
* accessor method failed or a type mismatch occurred
|
||||
*/
|
||||
void setPropertyValue(PropertyValue pv) throws BeansException;
|
||||
|
||||
@@ -144,7 +144,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
|
||||
* occured for specific properties during the batch update. This exception bundles
|
||||
* occurred for specific properties during the batch update. This exception bundles
|
||||
* all individual PropertyAccessExceptions. All other properties will have been
|
||||
* successfully updated.
|
||||
*/
|
||||
@@ -164,7 +164,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
|
||||
* occured for specific properties during the batch update. This exception bundles
|
||||
* occurred for specific properties during the batch update. This exception bundles
|
||||
* all individual PropertyAccessExceptions. All other properties will have been
|
||||
* successfully updated.
|
||||
* @see #setPropertyValues(PropertyValues, boolean, boolean)
|
||||
@@ -185,7 +185,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
|
||||
* occured for specific properties during the batch update. This exception bundles
|
||||
* occurred for specific properties during the batch update. This exception bundles
|
||||
* all individual PropertyAccessExceptions. All other properties will have been
|
||||
* successfully updated.
|
||||
* @see #setPropertyValues(PropertyValues, boolean, boolean)
|
||||
@@ -208,7 +208,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
|
||||
* occured for specific properties during the batch update. This exception bundles
|
||||
* occurred for specific properties during the batch update. This exception bundles
|
||||
* all individual PropertyAccessExceptions. All other properties will have been
|
||||
* successfully updated.
|
||||
*/
|
||||
|
||||
+15
-1
@@ -59,6 +59,7 @@ import org.springframework.beans.propertyeditors.FileEditor;
|
||||
import org.springframework.beans.propertyeditors.InputSourceEditor;
|
||||
import org.springframework.beans.propertyeditors.InputStreamEditor;
|
||||
import org.springframework.beans.propertyeditors.LocaleEditor;
|
||||
import org.springframework.beans.propertyeditors.PathEditor;
|
||||
import org.springframework.beans.propertyeditors.PatternEditor;
|
||||
import org.springframework.beans.propertyeditors.PropertiesEditor;
|
||||
import org.springframework.beans.propertyeditors.ReaderEditor;
|
||||
@@ -87,11 +88,21 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
|
||||
private static Class<?> pathClass;
|
||||
|
||||
private static Class<?> zoneIdClass;
|
||||
|
||||
static {
|
||||
ClassLoader cl = PropertyEditorRegistrySupport.class.getClassLoader();
|
||||
try {
|
||||
zoneIdClass = ClassUtils.forName("java.time.ZoneId", PropertyEditorRegistrySupport.class.getClassLoader());
|
||||
pathClass = ClassUtils.forName("java.nio.file.Path", cl);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Java 7 Path class not available
|
||||
pathClass = null;
|
||||
}
|
||||
try {
|
||||
zoneIdClass = ClassUtils.forName("java.time.ZoneId", cl);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Java 8 ZoneId class not available
|
||||
@@ -211,6 +222,9 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
this.defaultEditors.put(InputStream.class, new InputStreamEditor());
|
||||
this.defaultEditors.put(InputSource.class, new InputSourceEditor());
|
||||
this.defaultEditors.put(Locale.class, new LocaleEditor());
|
||||
if (pathClass != null) {
|
||||
this.defaultEditors.put(pathClass, new PathEditor());
|
||||
}
|
||||
this.defaultEditors.put(Pattern.class, new PatternEditor());
|
||||
this.defaultEditors.put(Properties.class, new PropertiesEditor());
|
||||
this.defaultEditors.put(Reader.class, new ReaderEditor());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -45,8 +45,6 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
|
||||
|
||||
private final Object value;
|
||||
|
||||
private Object source;
|
||||
|
||||
private boolean optional = false;
|
||||
|
||||
private boolean converted = false;
|
||||
@@ -78,12 +76,12 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
|
||||
Assert.notNull(original, "Original must not be null");
|
||||
this.name = original.getName();
|
||||
this.value = original.getValue();
|
||||
this.source = original.getSource();
|
||||
this.optional = original.isOptional();
|
||||
this.converted = original.converted;
|
||||
this.convertedValue = original.convertedValue;
|
||||
this.conversionNecessary = original.conversionNecessary;
|
||||
this.resolvedTokens = original.resolvedTokens;
|
||||
setSource(original.getSource());
|
||||
copyAttributesFrom(original);
|
||||
}
|
||||
|
||||
@@ -97,10 +95,10 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
|
||||
Assert.notNull(original, "Original must not be null");
|
||||
this.name = original.getName();
|
||||
this.value = newValue;
|
||||
this.source = original;
|
||||
this.optional = original.isOptional();
|
||||
this.conversionNecessary = original.conversionNecessary;
|
||||
this.resolvedTokens = original.resolvedTokens;
|
||||
setSource(original);
|
||||
copyAttributesFrom(original);
|
||||
}
|
||||
|
||||
@@ -129,16 +127,28 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
|
||||
*/
|
||||
public PropertyValue getOriginalPropertyValue() {
|
||||
PropertyValue original = this;
|
||||
while (original.source instanceof PropertyValue && original.source != original) {
|
||||
original = (PropertyValue) original.source;
|
||||
Object source = getSource();
|
||||
while (source instanceof PropertyValue && source != original) {
|
||||
original = (PropertyValue) source;
|
||||
source = original.getSource();
|
||||
}
|
||||
return original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this is an optional value, that is, to be ignored
|
||||
* when no corresponding property exists on the target class.
|
||||
* @since 3.0
|
||||
*/
|
||||
public void setOptional(boolean optional) {
|
||||
this.optional = optional;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this is an optional value, that is, to be ignored
|
||||
* when no corresponding property exists on the target class.
|
||||
* @since 3.0
|
||||
*/
|
||||
public boolean isOptional() {
|
||||
return this.optional;
|
||||
}
|
||||
@@ -180,7 +190,7 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
|
||||
PropertyValue otherPv = (PropertyValue) other;
|
||||
return (this.name.equals(otherPv.name) &&
|
||||
ObjectUtils.nullSafeEquals(this.value, otherPv.value) &&
|
||||
ObjectUtils.nullSafeEquals(this.source, otherPv.source));
|
||||
ObjectUtils.nullSafeEquals(getSource(), otherPv.getSource()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -269,7 +269,7 @@ class TypeConverterDelegate {
|
||||
}
|
||||
else {
|
||||
// convertedValue == null
|
||||
if (javaUtilOptionalEmpty != null && requiredType.equals(javaUtilOptionalEmpty.getClass())) {
|
||||
if (javaUtilOptionalEmpty != null && requiredType == javaUtilOptionalEmpty.getClass()) {
|
||||
convertedValue = javaUtilOptionalEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public abstract class TypeConverterSupport extends PropertyEditorRegistrySupport
|
||||
catch (IllegalStateException ex) {
|
||||
throw new ConversionNotSupportedException(value, requiredType, ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
catch (IllegalArgumentException ex) {
|
||||
throw new TypeMismatchException(value, requiredType, ex);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ public class BeanCreationException extends FatalBeanException {
|
||||
|
||||
/**
|
||||
* Add a related cause to this bean creation exception,
|
||||
* not being a direct cause of the failure but having occured
|
||||
* not being a direct cause of the failure but having occurred
|
||||
* earlier in the creation of the same bean instance.
|
||||
* @param ex the related cause to add
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -67,24 +67,27 @@ import org.springframework.core.ResolvableType;
|
||||
* 1. BeanNameAware's {@code setBeanName}<br>
|
||||
* 2. BeanClassLoaderAware's {@code setBeanClassLoader}<br>
|
||||
* 3. BeanFactoryAware's {@code setBeanFactory}<br>
|
||||
* 4. ResourceLoaderAware's {@code setResourceLoader}
|
||||
* 4. EnvironmentAware's {@code setEnvironment}
|
||||
* 5. EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
|
||||
* 6. ResourceLoaderAware's {@code setResourceLoader}
|
||||
* (only applicable when running in an application context)<br>
|
||||
* 5. ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
|
||||
* 7. ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
|
||||
* (only applicable when running in an application context)<br>
|
||||
* 6. MessageSourceAware's {@code setMessageSource}
|
||||
* 8. MessageSourceAware's {@code setMessageSource}
|
||||
* (only applicable when running in an application context)<br>
|
||||
* 7. ApplicationContextAware's {@code setApplicationContext}
|
||||
* 9. ApplicationContextAware's {@code setApplicationContext}
|
||||
* (only applicable when running in an application context)<br>
|
||||
* 8. ServletContextAware's {@code setServletContext}
|
||||
* 10. ServletContextAware's {@code setServletContext}
|
||||
* (only applicable when running in a web application context)<br>
|
||||
* 9. {@code postProcessBeforeInitialization} methods of BeanPostProcessors<br>
|
||||
* 10. InitializingBean's {@code afterPropertiesSet}<br>
|
||||
* 11. a custom init-method definition<br>
|
||||
* 12. {@code postProcessAfterInitialization} methods of BeanPostProcessors
|
||||
* 11. {@code postProcessBeforeInitialization} methods of BeanPostProcessors<br>
|
||||
* 12. InitializingBean's {@code afterPropertiesSet}<br>
|
||||
* 13. a custom init-method definition<br>
|
||||
* 14. {@code postProcessAfterInitialization} methods of BeanPostProcessors
|
||||
*
|
||||
* <p>On shutdown of a bean factory, the following lifecycle methods apply:<br>
|
||||
* 1. DisposableBean's {@code destroy}<br>
|
||||
* 2. a custom destroy-method definition
|
||||
* 1. {@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
|
||||
* 2. DisposableBean's {@code destroy}<br>
|
||||
* 3. a custom destroy-method definition
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
@@ -153,12 +156,12 @@ public interface BeanFactory {
|
||||
|
||||
/**
|
||||
* Return the bean instance that uniquely matches the given object type, if any.
|
||||
* @param requiredType type the bean must match; can be an interface or superclass.
|
||||
* {@code null} is disallowed.
|
||||
* <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
|
||||
* but may also be translated into a conventional by-name lookup based on the name
|
||||
* of the given type. For more extensive retrieval operations across sets of beans,
|
||||
* use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
|
||||
* @param requiredType type the bean must match; can be an interface or superclass.
|
||||
* {@code null} is disallowed.
|
||||
* @return an instance of the single bean matching the required type
|
||||
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -45,8 +45,8 @@ public class BeanNotOfRequiredTypeException extends BeansException {
|
||||
* the expected type
|
||||
*/
|
||||
public BeanNotOfRequiredTypeException(String beanName, Class<?> requiredType, Class<?> actualType) {
|
||||
super("Bean named '" + beanName + "' must be of type [" + requiredType.getName() +
|
||||
"], but was actually of type [" + actualType.getName() + "]");
|
||||
super("Bean named '" + beanName + "' is expected to be of type [" + requiredType.getName() +
|
||||
"] but was actually of type [" + actualType.getName() + "]");
|
||||
this.beanName = beanName;
|
||||
this.requiredType = requiredType;
|
||||
this.actualType = actualType;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,10 +17,10 @@
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
/**
|
||||
* Counterpart of BeanNameAware. Returns the bean name of an object.
|
||||
* Counterpart of {@link BeanNameAware}. Returns the bean name of an object.
|
||||
*
|
||||
* <p>This interface can be introduced to avoid a brittle dependence
|
||||
* on bean name in objects used with Spring IoC and Spring AOP.
|
||||
* <p>This interface can be introduced to avoid a brittle dependence on
|
||||
* bean name in objects used with Spring IoC and Spring AOP.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
@@ -29,7 +29,7 @@ package org.springframework.beans.factory;
|
||||
public interface NamedBean {
|
||||
|
||||
/**
|
||||
* Return the name of this bean in a Spring bean factory.
|
||||
* Return the name of this bean in a Spring bean factory, if known.
|
||||
*/
|
||||
String getBeanName();
|
||||
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -74,7 +75,7 @@ public class NoSuchBeanDefinitionException extends BeansException {
|
||||
* @param message detailed message describing the problem
|
||||
*/
|
||||
public NoSuchBeanDefinitionException(Class<?> type, String message) {
|
||||
super("No qualifying bean of type [" + type.getName() + "] is defined: " + message);
|
||||
super("No qualifying bean of type [" + ClassUtils.getQualifiedName(type) + "] is defined: " + message);
|
||||
this.beanType = type;
|
||||
}
|
||||
|
||||
@@ -85,7 +86,8 @@ public class NoSuchBeanDefinitionException extends BeansException {
|
||||
* @param message detailed message describing the problem
|
||||
*/
|
||||
public NoSuchBeanDefinitionException(Class<?> type, String dependencyDescription, String message) {
|
||||
super("No qualifying bean of type [" + type.getName() + "] found for dependency" +
|
||||
super("No qualifying bean" + (!StringUtils.hasLength(dependencyDescription) ?
|
||||
" of type [" + ClassUtils.getQualifiedName(type) + "]" : "") + " found for dependency" +
|
||||
(StringUtils.hasLength(dependencyDescription) ? " [" + dependencyDescription + "]" : "") +
|
||||
": " + message);
|
||||
this.beanType = type;
|
||||
|
||||
+7
-4
@@ -18,6 +18,7 @@ package org.springframework.beans.factory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Exception thrown when a bean depends on other beans or simple properties
|
||||
@@ -46,7 +47,7 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
|
||||
|
||||
super(resourceDescription, beanName,
|
||||
"Unsatisfied dependency expressed through bean property '" + propertyName + "'" +
|
||||
(msg != null ? ": " + msg : ""));
|
||||
(StringUtils.hasLength(msg) ? ": " + msg : ""));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,7 +60,7 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
|
||||
public UnsatisfiedDependencyException(
|
||||
String resourceDescription, String beanName, String propertyName, BeansException ex) {
|
||||
|
||||
this(resourceDescription, beanName, propertyName, (ex != null ? ex.getMessage() : ""));
|
||||
this(resourceDescription, beanName, propertyName, "");
|
||||
initCause(ex);
|
||||
}
|
||||
|
||||
@@ -74,7 +75,9 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
|
||||
public UnsatisfiedDependencyException(
|
||||
String resourceDescription, String beanName, InjectionPoint injectionPoint, String msg) {
|
||||
|
||||
super(resourceDescription, beanName, "Unsatisfied dependency expressed through " + injectionPoint + ": " + msg);
|
||||
super(resourceDescription, beanName,
|
||||
"Unsatisfied dependency expressed through " + injectionPoint +
|
||||
(StringUtils.hasLength(msg) ? ": " + msg : ""));
|
||||
this.injectionPoint = injectionPoint;
|
||||
}
|
||||
|
||||
@@ -89,7 +92,7 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
|
||||
public UnsatisfiedDependencyException(
|
||||
String resourceDescription, String beanName, InjectionPoint injectionPoint, BeansException ex) {
|
||||
|
||||
this(resourceDescription, beanName, injectionPoint, (ex != null ? ex.getMessage() : ""));
|
||||
this(resourceDescription, beanName, injectionPoint, "");
|
||||
initCause(ex);
|
||||
}
|
||||
|
||||
|
||||
+11
-7
@@ -577,7 +577,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
String autowiredBeanName = autowiredBeanNames.iterator().next();
|
||||
if (beanFactory.containsBean(autowiredBeanName)) {
|
||||
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
|
||||
this.cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName);
|
||||
this.cachedFieldValue = new ShortcutDependencyDescriptor(
|
||||
desc, autowiredBeanName, field.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -661,8 +662,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
String autowiredBeanName = it.next();
|
||||
if (beanFactory.containsBean(autowiredBeanName)) {
|
||||
if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
|
||||
this.cachedMethodArguments[i] =
|
||||
new ShortcutDependencyDescriptor(descriptors[i], autowiredBeanName);
|
||||
this.cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
|
||||
descriptors[i], autowiredBeanName, paramTypes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -705,16 +706,19 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
@SuppressWarnings("serial")
|
||||
private static class ShortcutDependencyDescriptor extends DependencyDescriptor {
|
||||
|
||||
private final String shortcutBeanName;
|
||||
private final String shortcutName;
|
||||
|
||||
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcutBeanName) {
|
||||
private final Class<?> requiredType;
|
||||
|
||||
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcutName, Class<?> requiredType) {
|
||||
super(original);
|
||||
this.shortcutBeanName = shortcutBeanName;
|
||||
this.shortcutName = shortcutName;
|
||||
this.requiredType = requiredType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveShortcut(BeanFactory beanFactory) {
|
||||
return resolveCandidate(this.shortcutBeanName, beanFactory);
|
||||
return resolveCandidate(this.shortcutName, this.requiredType, beanFactory);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,27 +18,30 @@ package org.springframework.beans.factory.annotation;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Convenience methods performing bean lookups related to annotations, for example
|
||||
* Spring's {@link Qualifier @Qualifier} annotation.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 3.1.2
|
||||
* @see BeanFactoryUtils
|
||||
*/
|
||||
public class BeanFactoryAnnotationUtils {
|
||||
public abstract class BeanFactoryAnnotationUtils {
|
||||
|
||||
/**
|
||||
* Obtain a bean of type {@code T} from the given {@code BeanFactory} declaring a
|
||||
@@ -48,9 +51,16 @@ public class BeanFactoryAnnotationUtils {
|
||||
* @param beanType the type of bean to retrieve
|
||||
* @param qualifier the qualifier for selecting between multiple bean matches
|
||||
* @return the matching bean of type {@code T} (never {@code null})
|
||||
* @throws NoUniqueBeanDefinitionException if multiple matching beans of type {@code T} found
|
||||
* @throws NoSuchBeanDefinitionException if no matching bean of type {@code T} found
|
||||
* @throws BeansException if the bean could not be created
|
||||
* @see BeanFactory#getBean(Class)
|
||||
*/
|
||||
public static <T> T qualifiedBeanOfType(BeanFactory beanFactory, Class<T> beanType, String qualifier) {
|
||||
public static <T> T qualifiedBeanOfType(BeanFactory beanFactory, Class<T> beanType, String qualifier)
|
||||
throws BeansException {
|
||||
|
||||
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||
|
||||
if (beanFactory instanceof ConfigurableListableBeanFactory) {
|
||||
// Full qualifier matching supported.
|
||||
return qualifiedBeanOfType((ConfigurableListableBeanFactory) beanFactory, beanType, qualifier);
|
||||
@@ -74,7 +84,6 @@ public class BeanFactoryAnnotationUtils {
|
||||
* @param beanType the type of bean to retrieve
|
||||
* @param qualifier the qualifier for selecting between multiple bean matches
|
||||
* @return the matching bean of type {@code T} (never {@code null})
|
||||
* @throws NoSuchBeanDefinitionException if no matching bean of type {@code T} found
|
||||
*/
|
||||
private static <T> T qualifiedBeanOfType(ConfigurableListableBeanFactory bf, Class<T> beanType, String qualifier) {
|
||||
String[] candidateBeans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(bf, beanType);
|
||||
@@ -82,8 +91,7 @@ public class BeanFactoryAnnotationUtils {
|
||||
for (String beanName : candidateBeans) {
|
||||
if (isQualifierMatch(qualifier, beanName, bf)) {
|
||||
if (matchingBean != null) {
|
||||
throw new NoSuchBeanDefinitionException(qualifier, "No unique " + beanType.getSimpleName() +
|
||||
" bean found for qualifier '" + qualifier + "'");
|
||||
throw new NoUniqueBeanDefinitionException(beanType, matchingBean, beanName);
|
||||
}
|
||||
matchingBean = beanName;
|
||||
}
|
||||
|
||||
+14
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.beans.factory.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
@@ -49,6 +50,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.5
|
||||
* @see AutowireCandidateQualifier
|
||||
* @see Qualifier
|
||||
@@ -225,8 +227,12 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
|
||||
qualifier = bd.getQualifier(ClassUtils.getShortName(type));
|
||||
}
|
||||
if (qualifier == null) {
|
||||
// First, check annotation on factory method, if applicable
|
||||
Annotation targetAnnotation = getFactoryMethodAnnotation(bd, type);
|
||||
// First, check annotation on qualified element, if any
|
||||
Annotation targetAnnotation = getQualifiedElementAnnotation(bd, type);
|
||||
// Then, check annotation on factory method, if applicable
|
||||
if (targetAnnotation == null) {
|
||||
targetAnnotation = getFactoryMethodAnnotation(bd, type);
|
||||
}
|
||||
if (targetAnnotation == null) {
|
||||
RootBeanDefinition dbd = getResolvedDecoratedDefinition(bd);
|
||||
if (dbd != null) {
|
||||
@@ -291,6 +297,11 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Annotation getQualifiedElementAnnotation(RootBeanDefinition bd, Class<? extends Annotation> type) {
|
||||
AnnotatedElement qualifiedElement = bd.getQualifiedElement();
|
||||
return (qualifiedElement != null ? AnnotationUtils.getAnnotation(qualifiedElement, type) : null);
|
||||
}
|
||||
|
||||
protected Annotation getFactoryMethodAnnotation(RootBeanDefinition bd, Class<? extends Annotation> type) {
|
||||
Method resolvedFactoryMethod = bd.getResolvedFactoryMethod();
|
||||
return (resolvedFactoryMethod != null ? AnnotationUtils.getAnnotation(resolvedFactoryMethod, type) : null);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -208,7 +208,7 @@ public abstract class AbstractFactoryBean<T>
|
||||
* <p>Invoked on initialization of this FactoryBean in case of
|
||||
* a singleton; else, on each {@link #getObject()} call.
|
||||
* @return the object returned by this factory
|
||||
* @throws Exception if an exception occured during object creation
|
||||
* @throws Exception if an exception occurred during object creation
|
||||
* @see #getObject()
|
||||
*/
|
||||
protected abstract T createInstance() throws Exception;
|
||||
|
||||
+47
-17
@@ -21,6 +21,8 @@ import java.util.Set;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
|
||||
/**
|
||||
* Extension of the {@link org.springframework.beans.factory.BeanFactory}
|
||||
@@ -154,15 +156,6 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
*/
|
||||
Object configureBean(Object existingBean, String beanName) throws BeansException;
|
||||
|
||||
/**
|
||||
* Resolve the specified dependency against the beans defined in this factory.
|
||||
* @param descriptor the descriptor for the dependency
|
||||
* @param beanName the name of the bean which declares the present dependency
|
||||
* @return the resolved object, or {@code null} if none found
|
||||
* @throws BeansException if dependency resolution failed
|
||||
*/
|
||||
Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Specialized methods for fine-grained control over the bean lifecycle
|
||||
@@ -312,18 +305,55 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
*/
|
||||
void destroyBean(Object existingBean);
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Delegate methods for resolving injection points
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Resolve the bean instance that uniquely matches the given object type, if any,
|
||||
* including its bean name.
|
||||
* <p>This is effectively a variant of {@link #getBean(Class)} which preserves the
|
||||
* bean name of the matching instance.
|
||||
* @param requiredType type the bean must match; can be an interface or superclass.
|
||||
* {@code null} is disallowed.
|
||||
* @return the bean name plus bean instance
|
||||
* @throws NoSuchBeanDefinitionException if no matching bean was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
|
||||
* @throws BeansException if the bean could not be created
|
||||
* @since 4.3.3
|
||||
* @see #getBean(Class)
|
||||
*/
|
||||
<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;
|
||||
|
||||
/**
|
||||
* Resolve the specified dependency against the beans defined in this factory.
|
||||
* @param descriptor the descriptor for the dependency
|
||||
* @param beanName the name of the bean which declares the present dependency
|
||||
* @param autowiredBeanNames a Set that all names of autowired beans (used for
|
||||
* resolving the present dependency) are supposed to be added to
|
||||
* @param typeConverter the TypeConverter to use for populating arrays and
|
||||
* collections
|
||||
* @param descriptor the descriptor for the dependency (field/method/constructor)
|
||||
* @param requestingBeanName the name of the bean which declares the given dependency
|
||||
* @return the resolved object, or {@code null} if none found
|
||||
* @throws BeansException if dependency resolution failed
|
||||
* @throws NoSuchBeanDefinitionException if no matching bean was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
|
||||
* @throws BeansException if dependency resolution failed for any other reason
|
||||
* @since 2.5
|
||||
* @see #resolveDependency(DependencyDescriptor, String, Set, TypeConverter)
|
||||
*/
|
||||
Object resolveDependency(DependencyDescriptor descriptor, String beanName,
|
||||
Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) throws BeansException;
|
||||
|
||||
/**
|
||||
* Resolve the specified dependency against the beans defined in this factory.
|
||||
* @param descriptor the descriptor for the dependency (field/method/constructor)
|
||||
* @param requestingBeanName the name of the bean which declares the given dependency
|
||||
* @param autowiredBeanNames a Set that all names of autowired beans (used for
|
||||
* resolving the given dependency) are supposed to be added to
|
||||
* @param typeConverter the TypeConverter to use for populating arrays and collections
|
||||
* @return the resolved object, or {@code null} if none found
|
||||
* @throws NoSuchBeanDefinitionException if no matching bean was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
|
||||
* @throws BeansException if dependency resolution failed for any other reason
|
||||
* @since 2.5
|
||||
* @see DependencyDescriptor
|
||||
*/
|
||||
Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
|
||||
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException;
|
||||
|
||||
}
|
||||
|
||||
+21
-16
@@ -172,21 +172,6 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the specified bean name, as a candidate result of the matching
|
||||
* algorithm for this dependency, to a bean instance from the given factory.
|
||||
* <p>The default implementation calls {@link BeanFactory#getBean(String)}.
|
||||
* Subclasses may provide additional arguments or other customizations.
|
||||
* @param beanName the bean name, as a candidate result for this dependency
|
||||
* @param beanFactory the associated factory
|
||||
* @return the bean instance (never {@code null})
|
||||
* @since 4.3
|
||||
* @see BeanFactory#getBean(String)
|
||||
*/
|
||||
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
|
||||
return beanFactory.getBean(beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a shortcut for this dependency against the given factory, for example
|
||||
* taking some pre-resolved information into account.
|
||||
@@ -196,12 +181,32 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
* pre-cached information while still receiving {@link InjectionPoint} exposure etc.
|
||||
* @param beanFactory the associated factory
|
||||
* @return the shortcut result if any, or {@code null} if none
|
||||
* @throws BeansException if the shortcut could not be obtained
|
||||
* @since 4.3.1
|
||||
*/
|
||||
public Object resolveShortcut(BeanFactory beanFactory) {
|
||||
public Object resolveShortcut(BeanFactory beanFactory) throws BeansException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the specified bean name, as a candidate result of the matching
|
||||
* algorithm for this dependency, to a bean instance from the given factory.
|
||||
* <p>The default implementation calls {@link BeanFactory#getBean(String)}.
|
||||
* Subclasses may provide additional arguments or other customizations.
|
||||
* @param beanName the bean name, as a candidate result for this dependency
|
||||
* @param requiredType the expected type of the bean (as an assertion)
|
||||
* @param beanFactory the associated factory
|
||||
* @return the bean instance (never {@code null})
|
||||
* @throws BeansException if the bean could not be obtained
|
||||
* @since 4.3.2
|
||||
* @see BeanFactory#getBean(String)
|
||||
*/
|
||||
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
|
||||
throws BeansException {
|
||||
|
||||
return beanFactory.getBean(beanName, requiredType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Increase this descriptor's nesting level.
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import org.springframework.beans.factory.NamedBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A simple holder for a given bean name plus bean instance.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.3.3
|
||||
* @see AutowireCapableBeanFactory#resolveNamedBean(Class)
|
||||
*/
|
||||
public class NamedBeanHolder<T> implements NamedBean {
|
||||
|
||||
private final String beanName;
|
||||
|
||||
private final T beanInstance;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new holder for the given bean name plus instance.
|
||||
* @param beanName the name of the bean
|
||||
* @param beanInstance the corresponding bean instance
|
||||
*/
|
||||
public NamedBeanHolder(String beanName, T beanInstance) {
|
||||
Assert.notNull(beanName, "Bean name must not be null");
|
||||
this.beanName = beanName;
|
||||
this.beanInstance = beanInstance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of the bean (never {@code null}).
|
||||
*/
|
||||
@Override
|
||||
public String getBeanName() {
|
||||
return this.beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the corresponding bean instance (can be {@code null}).
|
||||
*/
|
||||
public T getBeanInstance() {
|
||||
return this.beanInstance;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -95,7 +95,7 @@ public class PropertiesFactoryBean extends PropertiesLoaderSupport
|
||||
* <p>Invoked on initialization of this FactoryBean in case of a
|
||||
* shared singleton; else, on each {@link #getObject()} call.
|
||||
* @return the object returned by this factory
|
||||
* @throws IOException if an exception occured during properties loading
|
||||
* @throws IOException if an exception occurred during properties loading
|
||||
* @see #mergeProperties()
|
||||
*/
|
||||
protected Properties createProperties() throws IOException {
|
||||
|
||||
+13
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -325,8 +325,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException {
|
||||
return resolveDependency(descriptor, beanName, null, null);
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) throws BeansException {
|
||||
return resolveDependency(descriptor, requestingBeanName, null, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -624,10 +624,11 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
protected Class<?> determineTargetType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
|
||||
Class<?> targetType = mbd.getTargetType();
|
||||
if (targetType == null) {
|
||||
targetType = (mbd.getFactoryMethodName() != null ? getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
|
||||
targetType = (mbd.getFactoryMethodName() != null ?
|
||||
getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
|
||||
resolveBeanClass(mbd, beanName, typesToMatch));
|
||||
if (ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null) {
|
||||
mbd.setTargetType(targetType);
|
||||
mbd.resolvedTargetType = targetType;
|
||||
}
|
||||
}
|
||||
return targetType;
|
||||
@@ -802,10 +803,14 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
if (objectType.value != null) {
|
||||
return objectType.value;
|
||||
}
|
||||
else {
|
||||
// No type found for shortcut FactoryBean instance:
|
||||
// fall back to full creation of the FactoryBean instance.
|
||||
return super.getTypeForFactoryBean(beanName, mbd);
|
||||
}
|
||||
}
|
||||
|
||||
// No type found - fall back to full creation of the FactoryBean instance.
|
||||
return super.getTypeForFactoryBean(beanName, mbd);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -824,7 +829,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
|
||||
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
|
||||
if (exposedObject == null) {
|
||||
return exposedObject;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -115,7 +115,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
|
||||
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
|
||||
Object instance;
|
||||
if (ctor == null) {
|
||||
instance = BeanUtils.instantiate(subclass);
|
||||
instance = BeanUtils.instantiateClass(subclass);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
|
||||
+9
-8
@@ -609,8 +609,8 @@ class ConstructorResolver {
|
||||
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
|
||||
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
|
||||
|
||||
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
|
||||
this.beanFactory.getCustomTypeConverter() : bw);
|
||||
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
|
||||
TypeConverter converter = (customConverter != null ? customConverter : bw);
|
||||
BeanDefinitionValueResolver valueResolver =
|
||||
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
|
||||
|
||||
@@ -665,8 +665,8 @@ class ConstructorResolver {
|
||||
BeanWrapper bw, Class<?>[] paramTypes, String[] paramNames, Object methodOrCtor,
|
||||
boolean autowiring) throws UnsatisfiedDependencyException {
|
||||
|
||||
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
|
||||
this.beanFactory.getCustomTypeConverter() : bw);
|
||||
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
|
||||
TypeConverter converter = (customConverter != null ? customConverter : bw);
|
||||
|
||||
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
|
||||
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
|
||||
@@ -769,12 +769,13 @@ class ConstructorResolver {
|
||||
private Object[] resolvePreparedArguments(
|
||||
String beanName, RootBeanDefinition mbd, BeanWrapper bw, Member methodOrCtor, Object[] argsToResolve) {
|
||||
|
||||
Class<?>[] paramTypes = (methodOrCtor instanceof Method ?
|
||||
((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes());
|
||||
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
|
||||
this.beanFactory.getCustomTypeConverter() : bw);
|
||||
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
|
||||
TypeConverter converter = (customConverter != null ? customConverter : bw);
|
||||
BeanDefinitionValueResolver valueResolver =
|
||||
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
|
||||
Class<?>[] paramTypes = (methodOrCtor instanceof Method ?
|
||||
((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes());
|
||||
|
||||
Object[] resolvedArgs = new Object[argsToResolve.length];
|
||||
for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
|
||||
Object argValue = argsToResolve[argIndex];
|
||||
|
||||
+214
-114
@@ -32,7 +32,6 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -52,6 +51,7 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
|
||||
import org.springframework.beans.factory.CannotLoadBeanClassException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InjectionPoint;
|
||||
@@ -61,11 +61,13 @@ import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.SmartFactoryBean;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.config.NamedBeanHolder;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
@@ -335,43 +337,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
@Override
|
||||
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
|
||||
Assert.notNull(requiredType, "Required type must not be null");
|
||||
String[] beanNames = getBeanNamesForType(requiredType);
|
||||
if (beanNames.length > 1) {
|
||||
ArrayList<String> autowireCandidates = new ArrayList<String>();
|
||||
for (String beanName : beanNames) {
|
||||
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
|
||||
autowireCandidates.add(beanName);
|
||||
}
|
||||
}
|
||||
if (autowireCandidates.size() > 0) {
|
||||
beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
|
||||
}
|
||||
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);
|
||||
if (namedBean != null) {
|
||||
return namedBean.getBeanInstance();
|
||||
}
|
||||
if (beanNames.length == 1) {
|
||||
return getBean(beanNames[0], requiredType, args);
|
||||
}
|
||||
else if (beanNames.length > 1) {
|
||||
Map<String, Object> candidates = new HashMap<String, Object>();
|
||||
for (String beanName : beanNames) {
|
||||
candidates.put(beanName, getBean(beanName, requiredType, args));
|
||||
}
|
||||
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
|
||||
if (primaryCandidate != null) {
|
||||
return getBean(primaryCandidate, requiredType, args);
|
||||
}
|
||||
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
|
||||
if (priorityCandidate != null) {
|
||||
return getBean(priorityCandidate, requiredType, args);
|
||||
}
|
||||
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
|
||||
}
|
||||
else if (getParentBeanFactory() != null) {
|
||||
return getParentBeanFactory().getBean(requiredType, args);
|
||||
}
|
||||
else {
|
||||
throw new NoSuchBeanDefinitionException(requiredType);
|
||||
BeanFactory parent = getParentBeanFactory();
|
||||
if (parent != null) {
|
||||
return parent.getBean(requiredType, args);
|
||||
}
|
||||
throw new NoSuchBeanDefinitionException(requiredType);
|
||||
}
|
||||
|
||||
|
||||
@@ -651,13 +625,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
else if (containsSingleton(beanName)) {
|
||||
return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver);
|
||||
}
|
||||
else if (getParentBeanFactory() instanceof DefaultListableBeanFactory) {
|
||||
|
||||
BeanFactory parent = getParentBeanFactory();
|
||||
if (parent instanceof DefaultListableBeanFactory) {
|
||||
// No bean definition found in this factory -> delegate to parent.
|
||||
return ((DefaultListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor, resolver);
|
||||
return ((DefaultListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor, resolver);
|
||||
}
|
||||
else if (getParentBeanFactory() instanceof ConfigurableListableBeanFactory) {
|
||||
else if (parent instanceof ConfigurableListableBeanFactory) {
|
||||
// If no DefaultListableBeanFactory, can't pass the resolver along.
|
||||
return ((ConfigurableListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor);
|
||||
return ((ConfigurableListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor);
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
@@ -998,24 +974,86 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, String beanName,
|
||||
public <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException {
|
||||
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, (Object[]) null);
|
||||
if (namedBean != null) {
|
||||
return namedBean;
|
||||
}
|
||||
BeanFactory parent = getParentBeanFactory();
|
||||
if (parent instanceof AutowireCapableBeanFactory) {
|
||||
return ((AutowireCapableBeanFactory) parent).resolveNamedBean(requiredType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType, Object... args) throws BeansException {
|
||||
Assert.notNull(requiredType, "Required type must not be null");
|
||||
String[] candidateNames = getBeanNamesForType(requiredType);
|
||||
|
||||
if (candidateNames.length > 1) {
|
||||
List<String> autowireCandidates = new ArrayList<String>(candidateNames.length);
|
||||
for (String beanName : candidateNames) {
|
||||
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
|
||||
autowireCandidates.add(beanName);
|
||||
}
|
||||
}
|
||||
if (!autowireCandidates.isEmpty()) {
|
||||
candidateNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
if (candidateNames.length == 1) {
|
||||
String beanName = candidateNames[0];
|
||||
return new NamedBeanHolder<T>(beanName, getBean(beanName, requiredType, args));
|
||||
}
|
||||
else if (candidateNames.length > 1) {
|
||||
Map<String, Object> candidates = new LinkedHashMap<String, Object>(candidateNames.length);
|
||||
for (String beanName : candidateNames) {
|
||||
if (containsSingleton(beanName)) {
|
||||
candidates.put(beanName, getBean(beanName, requiredType, args));
|
||||
}
|
||||
else {
|
||||
candidates.put(beanName, getType(beanName));
|
||||
}
|
||||
}
|
||||
String candidateName = determinePrimaryCandidate(candidates, requiredType);
|
||||
if (candidateName == null) {
|
||||
candidateName = determineHighestPriorityCandidate(candidates, requiredType);
|
||||
}
|
||||
if (candidateName != null) {
|
||||
Object beanInstance = candidates.get(candidateName);
|
||||
if (beanInstance instanceof Class) {
|
||||
beanInstance = getBean(candidateName, requiredType, args);
|
||||
}
|
||||
return new NamedBeanHolder<T>(candidateName, (T) beanInstance);
|
||||
}
|
||||
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
|
||||
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
|
||||
|
||||
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
|
||||
if (descriptor.getDependencyType().equals(javaUtilOptionalClass)) {
|
||||
return new OptionalDependencyFactory().createOptionalDependency(descriptor, beanName);
|
||||
if (javaUtilOptionalClass == descriptor.getDependencyType()) {
|
||||
return new OptionalDependencyFactory().createOptionalDependency(descriptor, requestingBeanName);
|
||||
}
|
||||
else if (ObjectFactory.class == descriptor.getDependencyType() ||
|
||||
ObjectProvider.class == descriptor.getDependencyType()) {
|
||||
return new DependencyObjectProvider(descriptor, beanName);
|
||||
return new DependencyObjectProvider(descriptor, requestingBeanName);
|
||||
}
|
||||
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
|
||||
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, beanName);
|
||||
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
|
||||
}
|
||||
else {
|
||||
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, beanName);
|
||||
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
|
||||
descriptor, requestingBeanName);
|
||||
if (result == null) {
|
||||
result = doResolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter);
|
||||
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1053,13 +1091,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
|
||||
if (matchingBeans.isEmpty()) {
|
||||
if (descriptor.isRequired()) {
|
||||
raiseNoSuchBeanDefinitionException(type, descriptor.getResolvableType().toString(), descriptor);
|
||||
raiseNoMatchingBeanFound(type, descriptor.getResolvableType().toString(), descriptor);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String autowiredBeanName;
|
||||
Object instanceCandidate;
|
||||
|
||||
if (matchingBeans.size() > 1) {
|
||||
String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor);
|
||||
if (primaryBeanName == null) {
|
||||
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
|
||||
if (autowiredBeanName == null) {
|
||||
if (descriptor.isRequired() || !indicatesMultipleBeans(type)) {
|
||||
return descriptor.resolveNotUnique(type, matchingBeans);
|
||||
}
|
||||
@@ -1070,17 +1112,20 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (autowiredBeanNames != null) {
|
||||
autowiredBeanNames.add(primaryBeanName);
|
||||
}
|
||||
return matchingBeans.get(primaryBeanName);
|
||||
instanceCandidate = matchingBeans.get(autowiredBeanName);
|
||||
}
|
||||
// We have exactly one match.
|
||||
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
|
||||
else {
|
||||
// We have exactly one match.
|
||||
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
|
||||
autowiredBeanName = entry.getKey();
|
||||
instanceCandidate = entry.getValue();
|
||||
}
|
||||
|
||||
if (autowiredBeanNames != null) {
|
||||
autowiredBeanNames.add(entry.getKey());
|
||||
autowiredBeanNames.add(autowiredBeanName);
|
||||
}
|
||||
return entry.getValue();
|
||||
return (instanceCandidate instanceof Class ?
|
||||
descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
|
||||
}
|
||||
finally {
|
||||
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
|
||||
@@ -1093,9 +1138,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
Class<?> type = descriptor.getDependencyType();
|
||||
if (type.isArray()) {
|
||||
Class<?> componentType = type.getComponentType();
|
||||
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
|
||||
targetDesc.increaseNestingLevel();
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, targetDesc);
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
|
||||
new MultiElementDependencyDescriptor(descriptor));
|
||||
if (matchingBeans.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -1114,9 +1158,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (elementType == null) {
|
||||
return null;
|
||||
}
|
||||
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
|
||||
targetDesc.increaseNestingLevel();
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, targetDesc);
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
|
||||
new MultiElementDependencyDescriptor(descriptor));
|
||||
if (matchingBeans.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -1139,9 +1182,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (valueType == null) {
|
||||
return null;
|
||||
}
|
||||
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
|
||||
targetDesc.increaseNestingLevel();
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, targetDesc);
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
|
||||
new MultiElementDependencyDescriptor(descriptor));
|
||||
if (matchingBeans.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -1210,7 +1252,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
for (String candidateName : candidateNames) {
|
||||
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {
|
||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
|
||||
addCandidateEntry(result, candidateName, descriptor, requiredType);
|
||||
}
|
||||
}
|
||||
if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
|
||||
@@ -1218,14 +1260,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
|
||||
for (String candidateName : candidateNames) {
|
||||
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
|
||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
|
||||
addCandidateEntry(result, candidateName, descriptor, requiredType);
|
||||
}
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
// Consider self references before as a final pass
|
||||
for (String candidateName : candidateNames) {
|
||||
if (isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
|
||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
|
||||
addCandidateEntry(result, candidateName, descriptor, requiredType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1233,31 +1275,46 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an entry to the candidate map: a bean instance if available or just the resolved
|
||||
* type, preventing early bean initialization ahead of primary candidate selection.
|
||||
*/
|
||||
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
|
||||
DependencyDescriptor descriptor, Class<?> requiredType) {
|
||||
|
||||
if (descriptor instanceof MultiElementDependencyDescriptor || containsSingleton(candidateName)) {
|
||||
candidates.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
|
||||
}
|
||||
else {
|
||||
candidates.put(candidateName, getType(candidateName));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the autowire candidate in the given set of beans.
|
||||
* <p>Looks for {@code @Primary} and {@code @Priority} (in that order).
|
||||
* @param candidateBeans a Map of candidate names and candidate instances
|
||||
* @param candidates a Map of candidate names and candidate instances
|
||||
* that match the required type, as returned by {@link #findAutowireCandidates}
|
||||
* @param descriptor the target dependency to match against
|
||||
* @return the name of the autowire candidate, or {@code null} if none found
|
||||
*/
|
||||
protected String determineAutowireCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) {
|
||||
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
|
||||
Class<?> requiredType = descriptor.getDependencyType();
|
||||
String primaryCandidate = determinePrimaryCandidate(candidateBeans, requiredType);
|
||||
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
|
||||
if (primaryCandidate != null) {
|
||||
return primaryCandidate;
|
||||
}
|
||||
String priorityCandidate = determineHighestPriorityCandidate(candidateBeans, requiredType);
|
||||
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
|
||||
if (priorityCandidate != null) {
|
||||
return priorityCandidate;
|
||||
}
|
||||
// Fallback
|
||||
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
|
||||
String candidateBeanName = entry.getKey();
|
||||
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
|
||||
String candidateName = entry.getKey();
|
||||
Object beanInstance = entry.getValue();
|
||||
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
|
||||
matchesBeanName(candidateBeanName, descriptor.getDependencyName())) {
|
||||
return candidateBeanName;
|
||||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
|
||||
return candidateName;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -1265,15 +1322,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
/**
|
||||
* Determine the primary candidate in the given set of beans.
|
||||
* @param candidateBeans a Map of candidate names and candidate instances
|
||||
* that match the required type
|
||||
* @param candidates a Map of candidate names and candidate instances
|
||||
* (or candidate classes if not created yet) that match the required type
|
||||
* @param requiredType the target dependency type to match against
|
||||
* @return the name of the primary candidate, or {@code null} if none found
|
||||
* @see #isPrimary(String, Object)
|
||||
*/
|
||||
protected String determinePrimaryCandidate(Map<String, Object> candidateBeans, Class<?> requiredType) {
|
||||
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
|
||||
String primaryBeanName = null;
|
||||
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
|
||||
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
|
||||
String candidateBeanName = entry.getKey();
|
||||
Object beanInstance = entry.getValue();
|
||||
if (isPrimary(candidateBeanName, beanInstance)) {
|
||||
@@ -1281,8 +1338,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
|
||||
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
|
||||
if (candidateLocal && primaryLocal) {
|
||||
throw new NoUniqueBeanDefinitionException(requiredType, candidateBeans.size(),
|
||||
"more than one 'primary' bean found among candidates: " + candidateBeans.keySet());
|
||||
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
|
||||
"more than one 'primary' bean found among candidates: " + candidates.keySet());
|
||||
}
|
||||
else if (candidateLocal) {
|
||||
primaryBeanName = candidateBeanName;
|
||||
@@ -1297,29 +1354,30 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the candidate with the highest priority in the given set of beans. As
|
||||
* defined by the {@link org.springframework.core.Ordered} interface, the lowest
|
||||
* value has the highest priority.
|
||||
* @param candidateBeans a Map of candidate names and candidate instances
|
||||
* that match the required type
|
||||
* Determine the candidate with the highest priority in the given set of beans.
|
||||
* <p>Based on {@code @javax.annotation.Priority}. As defined by the related
|
||||
* {@link org.springframework.core.Ordered} interface, the lowest value has
|
||||
* the highest priority.
|
||||
* @param candidates a Map of candidate names and candidate instances
|
||||
* (or candidate classes if not created yet) that match the required type
|
||||
* @param requiredType the target dependency type to match against
|
||||
* @return the name of the candidate with the highest priority,
|
||||
* or {@code null} if none found
|
||||
* @see #getPriority(Object)
|
||||
*/
|
||||
protected String determineHighestPriorityCandidate(Map<String, Object> candidateBeans, Class<?> requiredType) {
|
||||
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
|
||||
String highestPriorityBeanName = null;
|
||||
Integer highestPriority = null;
|
||||
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
|
||||
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
|
||||
String candidateBeanName = entry.getKey();
|
||||
Object beanInstance = entry.getValue();
|
||||
Integer candidatePriority = getPriority(beanInstance);
|
||||
if (candidatePriority != null) {
|
||||
if (highestPriorityBeanName != null) {
|
||||
if (candidatePriority.equals(highestPriority)) {
|
||||
throw new NoUniqueBeanDefinitionException(requiredType, candidateBeans.size(),
|
||||
"Multiple beans found with the same priority ('" + highestPriority + "') " +
|
||||
"among candidates: " + candidateBeans.keySet());
|
||||
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
|
||||
"Multiple beans found with the same priority ('" + highestPriority +
|
||||
"') among candidates: " + candidates.keySet());
|
||||
}
|
||||
else if (candidatePriority < highestPriority) {
|
||||
highestPriorityBeanName = candidateBeanName;
|
||||
@@ -1346,9 +1404,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (containsBeanDefinition(beanName)) {
|
||||
return getMergedLocalBeanDefinition(beanName).isPrimary();
|
||||
}
|
||||
BeanFactory parentFactory = getParentBeanFactory();
|
||||
return (parentFactory instanceof DefaultListableBeanFactory &&
|
||||
((DefaultListableBeanFactory) parentFactory).isPrimary(beanName, beanInstance));
|
||||
BeanFactory parent = getParentBeanFactory();
|
||||
return (parent instanceof DefaultListableBeanFactory &&
|
||||
((DefaultListableBeanFactory) parent).isPrimary(beanName, beanInstance));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1392,17 +1450,44 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
|
||||
/**
|
||||
* Raise a NoSuchBeanDefinitionException for an unresolvable dependency.
|
||||
* Raise a NoSuchBeanDefinitionException or BeanNotOfRequiredTypeException
|
||||
* for an unresolvable dependency.
|
||||
*/
|
||||
private void raiseNoSuchBeanDefinitionException(
|
||||
Class<?> type, String dependencyDescription, DependencyDescriptor descriptor)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
private void raiseNoMatchingBeanFound(
|
||||
Class<?> type, String dependencyDescription, DependencyDescriptor descriptor) throws BeansException {
|
||||
|
||||
checkBeanNotOfRequiredType(type, descriptor);
|
||||
|
||||
throw new NoSuchBeanDefinitionException(type, dependencyDescription,
|
||||
"expected at least 1 bean which qualifies as autowire candidate for this dependency. " +
|
||||
"expected at least 1 bean which qualifies as autowire candidate. " +
|
||||
"Dependency annotations: " + ObjectUtils.nullSafeToString(descriptor.getAnnotations()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Raise a BeanNotOfRequiredTypeException for an unresolvable dependency, if applicable,
|
||||
* i.e. if the target type of the bean would match but an exposed proxy doesn't.
|
||||
*/
|
||||
private void checkBeanNotOfRequiredType(Class<?> type, DependencyDescriptor descriptor) {
|
||||
for (String beanName : this.beanDefinitionNames) {
|
||||
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
|
||||
Class<?> targetType = mbd.getTargetType();
|
||||
if (targetType != null && type.isAssignableFrom(targetType) &&
|
||||
isAutowireCandidate(beanName, mbd, descriptor, getAutowireCandidateResolver())) {
|
||||
// Probably a poxy interfering with target type match -> throw meaningful exception.
|
||||
Object beanInstance = getSingleton(beanName, false);
|
||||
Class<?> beanType = (beanInstance != null ? beanInstance.getClass() : predictBeanType(beanName, mbd));
|
||||
if (type != beanType) {
|
||||
throw new BeanNotOfRequiredTypeException(beanName, type, beanType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BeanFactory parent = getParentBeanFactory();
|
||||
if (parent instanceof DefaultListableBeanFactory) {
|
||||
((DefaultListableBeanFactory) parent).checkBeanNotOfRequiredType(type, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@@ -1473,18 +1558,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
private class OptionalDependencyFactory {
|
||||
|
||||
public Object createOptionalDependency(DependencyDescriptor descriptor, String beanName, final Object... args) {
|
||||
DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
|
||||
DependencyDescriptor descriptorToUse = new NestedDependencyDescriptor(descriptor) {
|
||||
@Override
|
||||
public boolean isRequired() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
|
||||
return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, args) :
|
||||
super.resolveCandidate(beanName, beanFactory));
|
||||
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
|
||||
return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, requiredType, args) :
|
||||
super.resolveCandidate(beanName, requiredType, beanFactory));
|
||||
}
|
||||
};
|
||||
descriptorToUse.increaseNestingLevel();
|
||||
return Optional.ofNullable(doResolveDependency(descriptorToUse, beanName, null, null));
|
||||
}
|
||||
}
|
||||
@@ -1502,9 +1586,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
private final String beanName;
|
||||
|
||||
public DependencyObjectProvider(DependencyDescriptor descriptor, String beanName) {
|
||||
this.descriptor = new DependencyDescriptor(descriptor);
|
||||
this.descriptor.increaseNestingLevel();
|
||||
this.optional = this.descriptor.getDependencyType().equals(javaUtilOptionalClass);
|
||||
this.descriptor = new NestedDependencyDescriptor(descriptor);
|
||||
this.optional = (this.descriptor.getDependencyType() == javaUtilOptionalClass);
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
@@ -1526,8 +1609,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
else {
|
||||
DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
|
||||
@Override
|
||||
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
|
||||
return beanFactory.getBean(beanName, args);
|
||||
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
|
||||
return ((AbstractBeanFactory) beanFactory).getBean(beanName, requiredType, args);
|
||||
}
|
||||
};
|
||||
return doResolveDependency(descriptorToUse, this.beanName, null, null);
|
||||
@@ -1620,13 +1703,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (beanDefinition == null) {
|
||||
return null;
|
||||
}
|
||||
List<Object> sources = new ArrayList<Object>();
|
||||
List<Object> sources = new ArrayList<Object>(2);
|
||||
Method factoryMethod = beanDefinition.getResolvedFactoryMethod();
|
||||
if (factoryMethod != null) {
|
||||
sources.add(factoryMethod);
|
||||
}
|
||||
Class<?> targetType = beanDefinition.getTargetType();
|
||||
if (targetType != null && !targetType.equals(obj.getClass())) {
|
||||
if (targetType != null && targetType != obj.getClass()) {
|
||||
sources.add(targetType);
|
||||
}
|
||||
return sources.toArray(new Object[sources.size()]);
|
||||
@@ -1643,4 +1726,21 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class NestedDependencyDescriptor extends DependencyDescriptor {
|
||||
|
||||
public NestedDependencyDescriptor(DependencyDescriptor original) {
|
||||
super(original);
|
||||
increaseNestingLevel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MultiElementDependencyDescriptor extends NestedDependencyDescriptor {
|
||||
|
||||
public MultiElementDependencyDescriptor(DependencyDescriptor original) {
|
||||
super(original);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -449,10 +449,10 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
}
|
||||
|
||||
private boolean isDependent(String beanName, String dependentBeanName, Set<String> alreadySeen) {
|
||||
String canonicalName = canonicalName(beanName);
|
||||
if (alreadySeen != null && alreadySeen.contains(beanName)) {
|
||||
return false;
|
||||
}
|
||||
String canonicalName = canonicalName(beanName);
|
||||
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
|
||||
if (dependentBeans == null) {
|
||||
return false;
|
||||
|
||||
+24
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -74,21 +74,31 @@ public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandid
|
||||
// No generic type -> we know it's a Class type-match, so no need to check again.
|
||||
return true;
|
||||
}
|
||||
|
||||
ResolvableType targetType = null;
|
||||
boolean cacheType = false;
|
||||
RootBeanDefinition rbd = null;
|
||||
if (bdHolder.getBeanDefinition() instanceof RootBeanDefinition) {
|
||||
rbd = (RootBeanDefinition) bdHolder.getBeanDefinition();
|
||||
}
|
||||
if (rbd != null) {
|
||||
// First, check factory method return type, if applicable
|
||||
targetType = getReturnTypeForFactoryMethod(rbd, descriptor);
|
||||
targetType = rbd.targetType;
|
||||
if (targetType == null) {
|
||||
RootBeanDefinition dbd = getResolvedDecoratedDefinition(rbd);
|
||||
if (dbd != null) {
|
||||
targetType = getReturnTypeForFactoryMethod(dbd, descriptor);
|
||||
cacheType = true;
|
||||
// First, check factory method return type, if applicable
|
||||
targetType = getReturnTypeForFactoryMethod(rbd, descriptor);
|
||||
if (targetType == null) {
|
||||
RootBeanDefinition dbd = getResolvedDecoratedDefinition(rbd);
|
||||
if (dbd != null) {
|
||||
targetType = dbd.targetType;
|
||||
if (targetType == null) {
|
||||
targetType = getReturnTypeForFactoryMethod(dbd, descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (targetType == null) {
|
||||
// Regular case: straight bean instance, with BeanFactory available.
|
||||
if (this.beanFactory != null) {
|
||||
@@ -106,7 +116,14 @@ public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandid
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetType == null || (descriptor.fallbackMatchAllowed() && targetType.hasUnresolvableGenerics())) {
|
||||
|
||||
if (targetType == null) {
|
||||
return true;
|
||||
}
|
||||
if (cacheType) {
|
||||
rbd.targetType = targetType;
|
||||
}
|
||||
if (descriptor.fallbackMatchAllowed() && targetType.hasUnresolvableGenerics()) {
|
||||
return true;
|
||||
}
|
||||
// Full check for complex generic type match...
|
||||
|
||||
+55
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
@@ -25,6 +26,7 @@ import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -48,22 +50,28 @@ import org.springframework.util.Assert;
|
||||
@SuppressWarnings("serial")
|
||||
public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
|
||||
boolean allowCaching = true;
|
||||
|
||||
private BeanDefinitionHolder decoratedDefinition;
|
||||
|
||||
private volatile Class<?> targetType;
|
||||
private AnnotatedElement qualifiedElement;
|
||||
|
||||
boolean allowCaching = true;
|
||||
|
||||
boolean isFactoryMethodUnique = false;
|
||||
|
||||
volatile ResolvableType targetType;
|
||||
|
||||
/** Package-visible field for caching the determined Class of a given bean definition */
|
||||
volatile Class<?> resolvedTargetType;
|
||||
|
||||
/** Package-visible field for caching the return type of a generically typed factory method */
|
||||
volatile Class<?> resolvedFactoryMethodReturnType;
|
||||
|
||||
/** Common lock for the four constructor fields below */
|
||||
final Object constructorArgumentLock = new Object();
|
||||
|
||||
/** Package-visible field for caching the resolved constructor or factory method */
|
||||
Object resolvedConstructorOrFactoryMethod;
|
||||
|
||||
/** Package-visible field for caching the return type of a generically typed factory method */
|
||||
volatile Class<?> resolvedFactoryMethodReturnType;
|
||||
|
||||
/** Package-visible field that marks the constructor arguments as resolved */
|
||||
boolean constructorArgumentsResolved = false;
|
||||
|
||||
@@ -73,6 +81,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
/** Package-visible field for caching partly prepared constructor arguments */
|
||||
Object[] preparedConstructorArguments;
|
||||
|
||||
/** Common lock for the two post-processing fields below */
|
||||
final Object postProcessingLock = new Object();
|
||||
|
||||
/** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied */
|
||||
@@ -125,7 +134,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
setBeanClass(beanClass);
|
||||
setAutowireMode(autowireMode);
|
||||
if (dependencyCheck && getResolvedAutowireMode() != AUTOWIRE_CONSTRUCTOR) {
|
||||
setDependencyCheck(RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
|
||||
setDependencyCheck(DEPENDENCY_CHECK_OBJECTS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,10 +180,11 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
*/
|
||||
public RootBeanDefinition(RootBeanDefinition original) {
|
||||
super(original);
|
||||
this.allowCaching = original.allowCaching;
|
||||
this.decoratedDefinition = original.decoratedDefinition;
|
||||
this.targetType = original.targetType;
|
||||
this.qualifiedElement = original.qualifiedElement;
|
||||
this.allowCaching = original.allowCaching;
|
||||
this.isFactoryMethodUnique = original.isFactoryMethodUnique;
|
||||
this.targetType = original.targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,19 +223,52 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
return this.decoratedDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the {@link AnnotatedElement} defining qualifiers,
|
||||
* to be used instead of the target class or factory method.
|
||||
* @since 4.3.3
|
||||
* @see #setTargetType(ResolvableType)
|
||||
* @see #getResolvedFactoryMethod()
|
||||
*/
|
||||
public void setQualifiedElement(AnnotatedElement qualifiedElement) {
|
||||
this.qualifiedElement = qualifiedElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link AnnotatedElement} defining qualifiers, if any.
|
||||
* Otherwise, the factory method and target class will be checked.
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public AnnotatedElement getQualifiedElement() {
|
||||
return this.qualifiedElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a generics-containing target type of this bean definition, if known in advance.
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public void setTargetType(ResolvableType targetType) {
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the target type of this bean definition, if known in advance.
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public void setTargetType(Class<?> targetType) {
|
||||
this.targetType = targetType;
|
||||
this.targetType = (targetType != null ? ResolvableType.forClass(targetType) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the target type of this bean definition, if known
|
||||
* (either specified in advance or resolved on first instantiation).
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public Class<?> getTargetType() {
|
||||
return this.targetType;
|
||||
if (this.resolvedTargetType != null) {
|
||||
return this.resolvedTargetType;
|
||||
}
|
||||
return (this.targetType != null ? this.targetType.resolve() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
||||
}
|
||||
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -154,9 +154,9 @@ public class CustomCollectionEditor extends PropertyEditorSupport {
|
||||
try {
|
||||
return collectionType.newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not instantiate collection class [" + collectionType.getName() + "]: " + ex.getMessage());
|
||||
"Could not instantiate collection class: " + collectionType.getName(), ex);
|
||||
}
|
||||
}
|
||||
else if (List.class == collectionType) {
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -132,9 +132,9 @@ public class CustomMapEditor extends PropertyEditorSupport {
|
||||
try {
|
||||
return mapType.newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not instantiate map class [" + mapType.getName() + "]: " + ex.getMessage());
|
||||
"Could not instantiate map class: " + mapType.getName(), ex);
|
||||
}
|
||||
}
|
||||
else if (SortedMap.class == mapType) {
|
||||
|
||||
+9
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -59,16 +59,14 @@ public class FileEditor extends PropertyEditorSupport {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new FileEditor,
|
||||
* using the default ResourceEditor underneath.
|
||||
* Create a new FileEditor, using a default ResourceEditor underneath.
|
||||
*/
|
||||
public FileEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new FileEditor,
|
||||
* using the given ResourceEditor underneath.
|
||||
* Create a new FileEditor, using the given ResourceEditor underneath.
|
||||
* @param resourceEditor the ResourceEditor to use
|
||||
*/
|
||||
public FileEditor(ResourceEditor resourceEditor) {
|
||||
@@ -86,8 +84,9 @@ public class FileEditor extends PropertyEditorSupport {
|
||||
|
||||
// Check whether we got an absolute file path without "file:" prefix.
|
||||
// For backwards compatibility, we'll consider those as straight file path.
|
||||
File file = null;
|
||||
if (!ResourceUtils.isUrl(text)) {
|
||||
File file = new File(text);
|
||||
file = new File(text);
|
||||
if (file.isAbsolute()) {
|
||||
setValue(file);
|
||||
return;
|
||||
@@ -99,18 +98,18 @@ public class FileEditor extends PropertyEditorSupport {
|
||||
Resource resource = (Resource) this.resourceEditor.getValue();
|
||||
|
||||
// If it's a URL or a path pointing to an existing resource, use it as-is.
|
||||
if (ResourceUtils.isUrl(text) || resource.exists()) {
|
||||
if (file == null || resource.exists()) {
|
||||
try {
|
||||
setValue(resource.getFile());
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not retrieve File for " + resource + ": " + ex.getMessage());
|
||||
"Could not retrieve file for " + resource + ": " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Create a relative File reference and hope for the best.
|
||||
setValue(new File(text));
|
||||
// Set a relative File reference and hope for the best.
|
||||
setValue(file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,16 +47,14 @@ public class InputStreamEditor extends PropertyEditorSupport {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new InputStreamEditor,
|
||||
* using the default ResourceEditor underneath.
|
||||
* Create a new InputStreamEditor, using the default ResourceEditor underneath.
|
||||
*/
|
||||
public InputStreamEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new InputStreamEditor,
|
||||
* using the given ResourceEditor underneath.
|
||||
* Create a new InputStreamEditor, using the given ResourceEditor underneath.
|
||||
* @param resourceEditor the ResourceEditor to use
|
||||
*/
|
||||
public InputStreamEditor(ResourceEditor resourceEditor) {
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans.propertyeditors;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.FileSystemNotFoundException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceEditor;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.lang.UsesJava7;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Editor for {@code java.nio.file.Path}, to directly populate a Path
|
||||
* property instead of using a String property as bridge.
|
||||
*
|
||||
* <p>Based on {@link Paths#get(URI)}'s resolution algorithm, checking
|
||||
* registered NIO file system providers, including the default file system
|
||||
* for "file:..." paths. Also supports Spring-style URL notation: any fully
|
||||
* qualified standard URL and Spring's special "classpath:" pseudo-URL, as
|
||||
* well as Spring's context-specific relative file paths. As a fallback, a
|
||||
* path will be resolved in the file system via {@code Paths#get(String)}
|
||||
* if no existing context-relative resource could be found.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.3.2
|
||||
* @see java.nio.file.Path
|
||||
* @see Paths#get(URI)
|
||||
* @see ResourceEditor
|
||||
* @see org.springframework.core.io.ResourceLoader
|
||||
* @see FileEditor
|
||||
* @see URLEditor
|
||||
*/
|
||||
@UsesJava7
|
||||
public class PathEditor extends PropertyEditorSupport {
|
||||
|
||||
private final ResourceEditor resourceEditor;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new PathEditor, using the default ResourceEditor underneath.
|
||||
*/
|
||||
public PathEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PathEditor, using the given ResourceEditor underneath.
|
||||
* @param resourceEditor the ResourceEditor to use
|
||||
*/
|
||||
public PathEditor(ResourceEditor resourceEditor) {
|
||||
Assert.notNull(resourceEditor, "ResourceEditor must not be null");
|
||||
this.resourceEditor = resourceEditor;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
boolean nioPathCandidate = !text.startsWith(ResourceLoader.CLASSPATH_URL_PREFIX);
|
||||
if (nioPathCandidate && !text.startsWith("/")) {
|
||||
try {
|
||||
URI uri = new URI(text);
|
||||
if (uri.getScheme() != null) {
|
||||
nioPathCandidate = false;
|
||||
// Let's try NIO file system providers via Paths.get(URI)
|
||||
setValue(Paths.get(uri).normalize());
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (URISyntaxException ex) {
|
||||
// Not a valid URI: Let's try as Spring resource location.
|
||||
}
|
||||
catch (FileSystemNotFoundException ex) {
|
||||
// URI scheme not registered for NIO:
|
||||
// Let's try URL protocol handlers via Spring's resource mechanism.
|
||||
}
|
||||
}
|
||||
|
||||
this.resourceEditor.setAsText(text);
|
||||
Resource resource = (Resource) this.resourceEditor.getValue();
|
||||
if (resource == null) {
|
||||
setValue(null);
|
||||
}
|
||||
else if (!resource.exists() && nioPathCandidate) {
|
||||
setValue(Paths.get(text).normalize());
|
||||
}
|
||||
else {
|
||||
try {
|
||||
setValue(resource.getFile().toPath());
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalArgumentException("Failed to retrieve file for " + resource, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsText() {
|
||||
Path value = (Path) getValue();
|
||||
return (value != null ? value.toString() : "");
|
||||
}
|
||||
|
||||
}
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,16 +47,14 @@ public class ReaderEditor extends PropertyEditorSupport {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ReaderEditor,
|
||||
* using the default ResourceEditor underneath.
|
||||
* Create a new ReaderEditor, using the default ResourceEditor underneath.
|
||||
*/
|
||||
public ReaderEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ReaderEditor,
|
||||
* using the given ResourceEditor underneath.
|
||||
* Create a new ReaderEditor, using the given ResourceEditor underneath.
|
||||
* @param resourceEditor the ResourceEditor to use
|
||||
*/
|
||||
public ReaderEditor(ResourceEditor resourceEditor) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -60,8 +60,7 @@ public class URIEditor extends PropertyEditorSupport {
|
||||
* standard URIs (not trying to resolve them into physical resources).
|
||||
*/
|
||||
public URIEditor() {
|
||||
this.classLoader = null;
|
||||
this.encode = true;
|
||||
this(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,7 +73,6 @@ public class URIEditor extends PropertyEditorSupport {
|
||||
this.encode = encode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new URIEditor, using the given ClassLoader to resolve
|
||||
* "classpath:" locations into physical resource URLs.
|
||||
@@ -82,8 +80,7 @@ public class URIEditor extends PropertyEditorSupport {
|
||||
* (may be {@code null} to indicate the default ClassLoader)
|
||||
*/
|
||||
public URIEditor(ClassLoader classLoader) {
|
||||
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
|
||||
this.encode = true;
|
||||
this(classLoader, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,7 +50,7 @@ public class URLEditor extends PropertyEditorSupport {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new URLEditor, using the default ResourceEditor underneath.
|
||||
* Create a new URLEditor, using a default ResourceEditor underneath.
|
||||
*/
|
||||
public URLEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
|
||||
+19
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,6 +33,7 @@ import org.springframework.beans.propertyeditors.ClassEditor;
|
||||
import org.springframework.beans.propertyeditors.FileEditor;
|
||||
import org.springframework.beans.propertyeditors.InputSourceEditor;
|
||||
import org.springframework.beans.propertyeditors.InputStreamEditor;
|
||||
import org.springframework.beans.propertyeditors.PathEditor;
|
||||
import org.springframework.beans.propertyeditors.ReaderEditor;
|
||||
import org.springframework.beans.propertyeditors.URIEditor;
|
||||
import org.springframework.beans.propertyeditors.URLEditor;
|
||||
@@ -43,6 +44,7 @@ import org.springframework.core.io.ResourceEditor;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.ResourceArrayPropertyEditor;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* PropertyEditorRegistrar implementation that populates a given
|
||||
@@ -58,6 +60,19 @@ import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
*/
|
||||
public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
|
||||
|
||||
private static Class<?> pathClass;
|
||||
|
||||
static {
|
||||
try {
|
||||
pathClass = ClassUtils.forName("java.nio.file.Path", ResourceEditorRegistrar.class.getClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Java 7 Path class not available
|
||||
pathClass = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final PropertyResolver propertyResolver;
|
||||
|
||||
private final ResourceLoader resourceLoader;
|
||||
@@ -103,6 +118,9 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
|
||||
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
|
||||
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
|
||||
doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
|
||||
if (pathClass != null) {
|
||||
doRegisterEditor(registry, pathClass, new PathEditor(baseEditor));
|
||||
}
|
||||
doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
|
||||
doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));
|
||||
|
||||
|
||||
+2
-18
@@ -1435,12 +1435,14 @@ public class DefaultListableBeanFactoryTests {
|
||||
public void testGetBeanByTypeWithPrimary() throws Exception {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||
bd1.setLazyInit(true);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
bd2.setPrimary(true);
|
||||
lbf.registerBeanDefinition("bd1", bd1);
|
||||
lbf.registerBeanDefinition("bd2", bd2);
|
||||
TestBean bean = lbf.getBean(TestBean.class);
|
||||
assertThat(bean.getBeanName(), equalTo("bd2"));
|
||||
assertFalse(lbf.containsSingleton("bd1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1760,24 +1762,6 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutowireBeanByTypeWithTwoMatchesAndParameterNameDiscovery() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("test", bd);
|
||||
lbf.registerBeanDefinition("spouse", bd2);
|
||||
try {
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
fail("Should have thrown UnsatisfiedDependencyException");
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getMessage().contains("test"));
|
||||
assertTrue(ex.getMessage().contains("spouse"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutowireBeanByTypeWithDependencyCheck() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
|
||||
+86
-7
@@ -41,6 +41,7 @@ import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
@@ -62,6 +63,7 @@ import org.springframework.tests.sample.beans.ITestBean;
|
||||
import org.springframework.tests.sample.beans.IndexedTestBean;
|
||||
import org.springframework.tests.sample.beans.NestedTestBean;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
@@ -1025,14 +1027,35 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryQualifierInjectionBean.class));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "testBean"));
|
||||
bf.registerBeanDefinition("testBean", bd);
|
||||
bf.registerBeanDefinition("testBean2", new RootBeanDefinition(TestBean.class));
|
||||
bf.registerBeanDefinition("dependencyBean", bd);
|
||||
bf.registerBeanDefinition("dependencyBean2", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
ObjectFactoryQualifierInjectionBean bean = (ObjectFactoryQualifierInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
assertSame(bf.getBean("dependencyBean"), bean.getTestBean());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryQualifierProviderInjection() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryQualifierInjectionBean.class));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.setQualifiedElement(ReflectionUtils.findMethod(getClass(), "testBeanQualifierProvider"));
|
||||
bf.registerBeanDefinition("dependencyBean", bd);
|
||||
bf.registerBeanDefinition("dependencyBean2", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
ObjectFactoryQualifierInjectionBean bean = (ObjectFactoryQualifierInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("dependencyBean"), bean.getTestBean());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Qualifier("testBean")
|
||||
private void testBeanQualifierProvider() {}
|
||||
|
||||
@Test
|
||||
public void testObjectFactorySerialization() throws Exception {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
@@ -1145,12 +1168,15 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
RootBeanDefinition tb1 = new RootBeanDefinition(TestBean.class);
|
||||
tb1.setPrimary(true);
|
||||
bf.registerBeanDefinition("testBean1", tb1);
|
||||
bf.registerBeanDefinition("testBean2", new RootBeanDefinition(TestBean.class));
|
||||
RootBeanDefinition tb2 = new RootBeanDefinition(TestBean.class);
|
||||
tb2.setLazyInit(true);
|
||||
bf.registerBeanDefinition("testBean2", tb2);
|
||||
|
||||
SmartObjectFactoryInjectionBean bean = (SmartObjectFactoryInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("testBean1"), bean.getTestBean());
|
||||
assertSame(bf.getBean("testBean1"), bean.getOptionalTestBean());
|
||||
assertSame(bf.getBean("testBean1"), bean.getUniqueTestBean());
|
||||
assertFalse(bf.containsSingleton("testBean2"));
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@@ -1584,11 +1610,12 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
rbd.setFactoryBeanName("mocksControl");
|
||||
rbd.setFactoryMethodName("createMock");
|
||||
rbd.getConstructorArgumentValues().addGenericArgumentValue(Repository.class);
|
||||
bf.registerBeanDefinition("integerRepo", rbd);
|
||||
rbd.setQualifiedElement(ReflectionUtils.findField(getClass(), "integerRepositoryQualifierProvider"));
|
||||
bf.registerBeanDefinition("integerRepository", rbd); // Bean name not matching qualifier
|
||||
|
||||
RepositoryFieldInjectionBeanWithQualifiers bean = (RepositoryFieldInjectionBeanWithQualifiers) bf.getBean("annotatedBean");
|
||||
Repository<?> sr = bf.getBean("stringRepo", Repository.class);
|
||||
Repository<?> ir = bf.getBean("integerRepo", Repository.class);
|
||||
Repository<?> ir = bf.getBean("integerRepository", Repository.class);
|
||||
assertSame(sr, bean.stringRepository);
|
||||
assertSame(ir, bean.integerRepository);
|
||||
assertSame(1, bean.stringRepositoryArray.length);
|
||||
@@ -1602,9 +1629,12 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertSame(1, bean.stringRepositoryMap.size());
|
||||
assertSame(1, bean.integerRepositoryMap.size());
|
||||
assertSame(sr, bean.stringRepositoryMap.get("stringRepo"));
|
||||
assertSame(ir, bean.integerRepositoryMap.get("integerRepo"));
|
||||
assertSame(ir, bean.integerRepositoryMap.get("integerRepository"));
|
||||
}
|
||||
|
||||
@Qualifier("integerRepo")
|
||||
private Repository<?> integerRepositoryQualifierProvider;
|
||||
|
||||
@Test
|
||||
public void testGenericsBasedFieldInjectionWithSimpleMatch() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
@@ -2047,6 +2077,24 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertSame(bean2, bean1.gi2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericsBasedInjectionWithBeanDefinitionTargetResolvableType() throws Exception {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(GenericInterface2Bean.class);
|
||||
bd1.setTargetType(ResolvableType.forClassWithGenerics(GenericInterface2Bean.class, String.class));
|
||||
bf.registerBeanDefinition("bean1", bd1);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(GenericInterface2Bean.class);
|
||||
bd2.setTargetType(ResolvableType.forClassWithGenerics(GenericInterface2Bean.class, Integer.class));
|
||||
bf.registerBeanDefinition("bean2", bd2);
|
||||
bf.registerBeanDefinition("bean3", new RootBeanDefinition(MultiGenericFieldInjection.class));
|
||||
|
||||
assertEquals("bean1 a bean2 123", bf.getBean("bean3").toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCircularTypeReference() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
@@ -3139,6 +3187,37 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
|
||||
public static class GenericInterface2Bean<K> implements GenericInterface2<K>, BeanNameAware {
|
||||
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
public void setBeanName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String doSomethingMoreGeneric(K o) {
|
||||
return this.name + " " + o;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class MultiGenericFieldInjection {
|
||||
|
||||
@Autowired
|
||||
private GenericInterface2<String> stringBean;
|
||||
|
||||
@Autowired
|
||||
private GenericInterface2<Integer> integerBean;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.stringBean.doSomethingMoreGeneric("a") + " " + this.integerBean.doSomethingMoreGeneric(123);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static class PlainGenericInterface2Impl implements GenericInterface2 {
|
||||
|
||||
|
||||
+23
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -41,6 +41,7 @@ public class LookupAnnotationTests {
|
||||
aabpp.setBeanFactory(beanFactory);
|
||||
beanFactory.addBeanPostProcessor(aabpp);
|
||||
beanFactory.registerBeanDefinition("abstractBean", new RootBeanDefinition(AbstractBean.class));
|
||||
beanFactory.registerBeanDefinition("beanConsumer", new RootBeanDefinition(BeanConsumer.class));
|
||||
RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class);
|
||||
tbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
beanFactory.registerBeanDefinition("testBean", tbd);
|
||||
@@ -53,6 +54,7 @@ public class LookupAnnotationTests {
|
||||
assertNotNull(bean);
|
||||
Object expected = bean.get();
|
||||
assertEquals(TestBean.class, expected.getClass());
|
||||
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -62,6 +64,7 @@ public class LookupAnnotationTests {
|
||||
TestBean expected = bean.get("haha");
|
||||
assertEquals(TestBean.class, expected.getClass());
|
||||
assertEquals("haha", expected.getName());
|
||||
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,6 +74,7 @@ public class LookupAnnotationTests {
|
||||
TestBean expected = bean.getOneArgument("haha");
|
||||
assertEquals(TestBean.class, expected.getClass());
|
||||
assertEquals("haha", expected.getName());
|
||||
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -81,6 +85,7 @@ public class LookupAnnotationTests {
|
||||
assertEquals(TestBean.class, expected.getClass());
|
||||
assertEquals("haha", expected.getName());
|
||||
assertEquals(72, expected.getAge());
|
||||
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -93,6 +98,16 @@ public class LookupAnnotationTests {
|
||||
}
|
||||
catch (AbstractMethodError ex) {
|
||||
}
|
||||
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithEarlyInjection() {
|
||||
AbstractBean bean = beanFactory.getBean("beanConsumer", BeanConsumer.class).abstractBean;
|
||||
assertNotNull(bean);
|
||||
Object expected = bean.get();
|
||||
assertEquals(TestBean.class, expected.getClass());
|
||||
assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,4 +128,11 @@ public class LookupAnnotationTests {
|
||||
public abstract TestBean getThreeArguments(String name, int age, int anotherArg);
|
||||
}
|
||||
|
||||
|
||||
public static class BeanConsumer {
|
||||
|
||||
@Autowired
|
||||
AbstractBean abstractBean;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -126,6 +126,7 @@ public class BeanDefinitionTests {
|
||||
bd.getConstructorArgumentValues().addIndexedArgumentValue(1, new Integer(5));
|
||||
bd.getPropertyValues().add("name", "myName");
|
||||
bd.getPropertyValues().add("age", "99");
|
||||
bd.setQualifiedElement(getClass());
|
||||
|
||||
GenericBeanDefinition childBd = new GenericBeanDefinition();
|
||||
childBd.setParentName("bd");
|
||||
@@ -138,6 +139,7 @@ public class BeanDefinitionTests {
|
||||
|
||||
mergedBd.getConstructorArgumentValues().getArgumentValue(1, null).setValue(new Integer(9));
|
||||
assertEquals(new Integer(5), bd.getConstructorArgumentValues().getArgumentValue(1, null).getValue());
|
||||
assertEquals(getClass(), bd.getQualifiedElement());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,21 +28,22 @@ import static org.junit.Assert.*;
|
||||
/**
|
||||
* @author Thomas Risberg
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public final class FileEditorTests {
|
||||
public class FileEditorTests {
|
||||
|
||||
@Test
|
||||
public void testClasspathFileName() throws Exception {
|
||||
PropertyEditor fileEditor = new FileEditor();
|
||||
fileEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/"
|
||||
+ ClassUtils.getShortName(getClass()) + ".class");
|
||||
fileEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".class");
|
||||
Object value = fileEditor.getValue();
|
||||
assertTrue(value instanceof File);
|
||||
File file = (File) value;
|
||||
assertTrue(file.exists());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWithNonExistentResource() throws Exception {
|
||||
PropertyEditor propertyEditor = new FileEditor();
|
||||
propertyEditor.setAsText("classpath:no_way_this_file_is_found.doc");
|
||||
@@ -71,34 +72,29 @@ public final class FileEditorTests {
|
||||
@Test
|
||||
public void testUnqualifiedFileNameFound() throws Exception {
|
||||
PropertyEditor fileEditor = new FileEditor();
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass())
|
||||
+ ".class";
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".class";
|
||||
fileEditor.setAsText(fileName);
|
||||
Object value = fileEditor.getValue();
|
||||
assertTrue(value instanceof File);
|
||||
File file = (File) value;
|
||||
assertTrue(file.exists());
|
||||
String absolutePath = file.getAbsolutePath();
|
||||
if (File.separatorChar == '\\') {
|
||||
absolutePath = absolutePath.replace('\\', '/');
|
||||
}
|
||||
String absolutePath = file.getAbsolutePath().replace('\\', '/');
|
||||
assertTrue(absolutePath.endsWith(fileName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnqualifiedFileNameNotFound() throws Exception {
|
||||
PropertyEditor fileEditor = new FileEditor();
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass())
|
||||
+ ".clazz";
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".clazz";
|
||||
fileEditor.setAsText(fileName);
|
||||
Object value = fileEditor.getValue();
|
||||
assertTrue(value instanceof File);
|
||||
File file = (File) value;
|
||||
assertFalse(file.exists());
|
||||
String absolutePath = file.getAbsolutePath();
|
||||
if (File.separatorChar == '\\') {
|
||||
absolutePath = absolutePath.replace('\\', '/');
|
||||
}
|
||||
String absolutePath = file.getAbsolutePath().replace('\\', '/');
|
||||
assertTrue(absolutePath.endsWith(fileName));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -60,9 +60,8 @@ public class InputStreamEditorTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWhenResourceDoesNotExist() throws Exception {
|
||||
String resource = "classpath:bingo!";
|
||||
InputStreamEditor editor = new InputStreamEditor();
|
||||
editor.setAsText(resource);
|
||||
editor.setAsText("classpath:bingo!");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans.propertyeditors;
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.3.2
|
||||
*/
|
||||
public class PathEditorTests {
|
||||
|
||||
@Test
|
||||
public void testClasspathPathName() throws Exception {
|
||||
PropertyEditor pathEditor = new PathEditor();
|
||||
pathEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".class");
|
||||
Object value = pathEditor.getValue();
|
||||
assertTrue(value instanceof Path);
|
||||
Path path = (Path) value;
|
||||
assertTrue(path.toFile().exists());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWithNonExistentResource() throws Exception {
|
||||
PropertyEditor propertyEditor = new PathEditor();
|
||||
propertyEditor.setAsText("classpath:/no_way_this_file_is_found.doc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithNonExistentPath() throws Exception {
|
||||
PropertyEditor pathEditor = new PathEditor();
|
||||
pathEditor.setAsText("file:/no_way_this_file_is_found.doc");
|
||||
Object value = pathEditor.getValue();
|
||||
assertTrue(value instanceof Path);
|
||||
Path path = (Path) value;
|
||||
assertTrue(!path.toFile().exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbsolutePath() throws Exception {
|
||||
PropertyEditor pathEditor = new PathEditor();
|
||||
pathEditor.setAsText("/no_way_this_file_is_found.doc");
|
||||
Object value = pathEditor.getValue();
|
||||
assertTrue(value instanceof Path);
|
||||
Path path = (Path) value;
|
||||
assertTrue(!path.toFile().exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnqualifiedPathNameFound() throws Exception {
|
||||
PropertyEditor pathEditor = new PathEditor();
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".class";
|
||||
pathEditor.setAsText(fileName);
|
||||
Object value = pathEditor.getValue();
|
||||
assertTrue(value instanceof Path);
|
||||
Path path = (Path) value;
|
||||
File file = path.toFile();
|
||||
assertTrue(file.exists());
|
||||
String absolutePath = file.getAbsolutePath();
|
||||
if (File.separatorChar == '\\') {
|
||||
absolutePath = absolutePath.replace('\\', '/');
|
||||
}
|
||||
assertTrue(absolutePath.endsWith(fileName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnqualifiedPathNameNotFound() throws Exception {
|
||||
PropertyEditor pathEditor = new PathEditor();
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".clazz";
|
||||
pathEditor.setAsText(fileName);
|
||||
Object value = pathEditor.getValue();
|
||||
assertTrue(value instanceof Path);
|
||||
Path path = (Path) value;
|
||||
File file = path.toFile();
|
||||
assertFalse(file.exists());
|
||||
String absolutePath = file.getAbsolutePath();
|
||||
if (File.separatorChar == '\\') {
|
||||
absolutePath = absolutePath.replace('\\', '/');
|
||||
}
|
||||
assertTrue(absolutePath.endsWith(fileName));
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,7 +34,7 @@ public class ReaderEditorTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCtorWithNullResourceEditor() throws Exception {
|
||||
new InputStreamEditor(null);
|
||||
new ReaderEditor(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+11
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,15 +31,6 @@ import static org.junit.Assert.*;
|
||||
*/
|
||||
public class URIEditorTests {
|
||||
|
||||
private void doTestURI(String uriSpec) {
|
||||
PropertyEditor uriEditor = new URIEditor();
|
||||
uriEditor.setAsText(uriSpec);
|
||||
Object value = uriEditor.getValue();
|
||||
assertTrue(value instanceof URI);
|
||||
URI uri = (URI) value;
|
||||
assertEquals(uriSpec, uri.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void standardURI() throws Exception {
|
||||
doTestURI("mailto:juergen.hoeller@interface21.com");
|
||||
@@ -141,4 +132,14 @@ public class URIEditorTests {
|
||||
assertEquals("http://example.com/spaces%20and%20%E2%82%AC", uri.toASCIIString());
|
||||
}
|
||||
|
||||
|
||||
private void doTestURI(String uriSpec) {
|
||||
PropertyEditor uriEditor = new URIEditor();
|
||||
uriEditor.setAsText(uriSpec);
|
||||
Object value = uriEditor.getValue();
|
||||
assertTrue(value instanceof URI);
|
||||
URI uri = (URI) value;
|
||||
assertEquals(uriSpec, uri.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,7 +29,12 @@ import static org.junit.Assert.*;
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class URLEditorTests {
|
||||
public class URLEditorTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCtorWithNullResourceEditor() throws Exception {
|
||||
new URLEditor(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStandardURI() throws Exception {
|
||||
@@ -63,7 +68,7 @@ public final class URLEditorTests {
|
||||
assertTrue(!url.getProtocol().startsWith("classpath"));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWithNonExistentResource() throws Exception {
|
||||
PropertyEditor urlEditor = new URLEditor();
|
||||
urlEditor.setAsText("gonna:/freak/in/the/morning/freak/in/the.evening");
|
||||
@@ -83,9 +88,4 @@ public final class URLEditorTests {
|
||||
assertEquals("", urlEditor.getAsText());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testCtorWithNullResourceEditor() throws Exception {
|
||||
new URLEditor(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -223,7 +223,7 @@ public class TestBean implements BeanNameAware, BeanFactoryAware, ITestBean, IOt
|
||||
|
||||
@Override
|
||||
public ITestBean[] getSpouses() {
|
||||
return (spouse != null ? new ITestBean[]{spouse} : null);
|
||||
return (spouse != null ? new ITestBean[] {spouse} : null);
|
||||
}
|
||||
|
||||
public String getTouchy() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
|
||||
+1
-1
@@ -7,6 +7,6 @@
|
||||
* <p>Note: EhCache 3.x lives in a different package namespace
|
||||
* and is not covered by the traditional support classes here.
|
||||
* Instead, consider using it through JCache (JSR-107), with
|
||||
* Spring's support in {@link org.springframework.cache.jcache}.
|
||||
* Spring's support in {@code org.springframework.cache.jcache}.
|
||||
*/
|
||||
package org.springframework.cache.ehcache;
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ abstract class AbstractCacheInterceptor<O extends AbstractJCacheOperation<A>, A
|
||||
/**
|
||||
* Convert the collection of caches in a single expected element.
|
||||
* <p>Throw an {@link IllegalStateException} if the collection holds more than one element
|
||||
* @return the singe element or {@code null} if the collection is empty
|
||||
* @return the single element or {@code null} if the collection is empty
|
||||
*/
|
||||
static Cache extractFrom(Collection<? extends Cache> caches) {
|
||||
if (CollectionUtils.isEmpty(caches)) {
|
||||
|
||||
+3
-1
@@ -69,7 +69,9 @@ public @interface CacheEvict {
|
||||
* following meta-data:
|
||||
* <ul>
|
||||
* <li>{@code #result} for a reference to the result of the method invocation, which
|
||||
* can only be used if {@link #beforeInvocation()} is {@code false}.</li>
|
||||
* can only be used if {@link #beforeInvocation()} is {@code false}. For supported
|
||||
* wrappers such as {@code Optional}, {@code #result} refers to the actual object,
|
||||
* not the wrapper</li>
|
||||
* <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for
|
||||
* references to the {@link java.lang.reflect.Method method}, target object, and
|
||||
* affected cache(s) respectively.</li>
|
||||
|
||||
+9
-3
@@ -31,7 +31,9 @@ import org.springframework.core.annotation.AliasFor;
|
||||
*
|
||||
* <p>In contrast to the {@link Cacheable @Cacheable} annotation, this annotation
|
||||
* does not cause the advised method to be skipped. Rather, it always causes the
|
||||
* method to be invoked and its result to be stored in the associated cache.
|
||||
* method to be invoked and its result to be stored in the associated cache. Note
|
||||
* that Java8's {@code Optional} return types are automatically handled and its
|
||||
* content is stored in the cache if present.
|
||||
*
|
||||
* <p>This annotation may be used as a <em>meta-annotation</em> to create custom
|
||||
* <em>composed annotations</em> with attribute overrides.
|
||||
@@ -73,7 +75,9 @@ public @interface CachePut {
|
||||
* <p>The SpEL expression evaluates against a dedicated context that provides the
|
||||
* following meta-data:
|
||||
* <ul>
|
||||
* <li>{@code #result} for a reference to the result of the method invocation.</li>
|
||||
* <li>{@code #result} for a reference to the result of the method invocation. For
|
||||
* supported wrappers such as {@code Optional}, {@code #result} refers to the actual
|
||||
* object, not the wrapper</li>
|
||||
* <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for
|
||||
* references to the {@link java.lang.reflect.Method method}, target object, and
|
||||
* affected cache(s) respectively.</li>
|
||||
@@ -138,7 +142,9 @@ public @interface CachePut {
|
||||
* <p>The SpEL expression evaluates against a dedicated context that provides the
|
||||
* following meta-data:
|
||||
* <ul>
|
||||
* <li>{@code #result} for a reference to the result of the method invocation.</li>
|
||||
* <li>{@code #result} for a reference to the result of the method invocation. For
|
||||
* supported wrappers such as {@code Optional}, {@code #result} refers to the actual
|
||||
* object, not the wrapper</li>
|
||||
* <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for
|
||||
* references to the {@link java.lang.reflect.Method method}, target object, and
|
||||
* affected cache(s) respectively.</li>
|
||||
|
||||
+6
-2
@@ -38,7 +38,9 @@ import org.springframework.core.annotation.AliasFor;
|
||||
* replace the default one (see {@link #keyGenerator}).
|
||||
*
|
||||
* <p>If no value is found in the cache for the computed key, the target method
|
||||
* will be invoked and the returned value stored in the associated cache.
|
||||
* will be invoked and the returned value stored in the associated cache. Note
|
||||
* that Java8's {@code Optional} return types are automatically handled and its
|
||||
* content is stored in the cache if present.
|
||||
*
|
||||
* <p>This annotation may be used as a <em>meta-annotation</em> to create custom
|
||||
* <em>composed annotations</em> with attribute overrides.
|
||||
@@ -144,7 +146,9 @@ public @interface Cacheable {
|
||||
* <p>The SpEL expression evaluates against a dedicated context that provides the
|
||||
* following meta-data:
|
||||
* <ul>
|
||||
* <li>{@code #result} for a reference to the result of the method invocation.</li>
|
||||
* <li>{@code #result} for a reference to the result of the method invocation. For
|
||||
* supported wrappers such as {@code Optional}, {@code #result} refers to the actual
|
||||
* object, not the wrapper</li>
|
||||
* <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for
|
||||
* references to the {@link java.lang.reflect.Method method}, target object, and
|
||||
* affected cache(s) respectively.</li>
|
||||
|
||||
Vendored
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,7 +52,7 @@ public class CachingConfigurationSelector extends AdviceModeImportSelector<Enabl
|
||||
private static final boolean jsr107Present = ClassUtils.isPresent(
|
||||
"javax.cache.Cache", CachingConfigurationSelector.class.getClassLoader());
|
||||
|
||||
private static final boolean jCacheImplPresent = ClassUtils.isPresent(
|
||||
private static final boolean jcacheImplPresent = ClassUtils.isPresent(
|
||||
PROXY_JCACHE_CONFIGURATION_CLASS, CachingConfigurationSelector.class.getClassLoader());
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ public class CachingConfigurationSelector extends AdviceModeImportSelector<Enabl
|
||||
List<String> result = new ArrayList<String>();
|
||||
result.add(AutoProxyRegistrar.class.getName());
|
||||
result.add(ProxyCachingConfiguration.class.getName());
|
||||
if (jsr107Present && jCacheImplPresent) {
|
||||
if (jsr107Present && jcacheImplPresent) {
|
||||
result.add(PROXY_JCACHE_CONFIGURATION_CLASS);
|
||||
}
|
||||
return result.toArray(new String[result.size()]);
|
||||
@@ -94,7 +94,7 @@ public class CachingConfigurationSelector extends AdviceModeImportSelector<Enabl
|
||||
private String[] getAspectJImports() {
|
||||
List<String> result = new ArrayList<String>();
|
||||
result.add(CACHE_ASPECT_CONFIGURATION_CLASS_NAME);
|
||||
if (jsr107Present && jCacheImplPresent) {
|
||||
if (jsr107Present && jcacheImplPresent) {
|
||||
result.add(JCACHE_ASPECT_CONFIGURATION_CLASS_NAME);
|
||||
}
|
||||
return result.toArray(new String[result.size()]);
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -60,11 +60,10 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
|
||||
private static final String JCACHE_ASPECT_CLASS_NAME =
|
||||
"org.springframework.cache.aspectj.JCacheCacheAspect";
|
||||
|
||||
|
||||
private static final boolean jsr107Present = ClassUtils.isPresent(
|
||||
"javax.cache.Cache", AnnotationDrivenCacheBeanDefinitionParser.class.getClassLoader());
|
||||
|
||||
private static final boolean jCacheImplPresent = ClassUtils.isPresent(
|
||||
private static final boolean jcacheImplPresent = ClassUtils.isPresent(
|
||||
"org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource",
|
||||
AnnotationDrivenCacheBeanDefinitionParser.class.getClassLoader());
|
||||
|
||||
@@ -91,7 +90,7 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
|
||||
|
||||
private void registerCacheAspect(Element element, ParserContext parserContext) {
|
||||
SpringCachingConfigurer.registerCacheAspect(element, parserContext);
|
||||
if (jsr107Present && jCacheImplPresent) { // Register JCache aspect
|
||||
if (jsr107Present && jcacheImplPresent) {
|
||||
JCacheCachingConfigurer.registerCacheAspect(element, parserContext);
|
||||
}
|
||||
}
|
||||
@@ -99,7 +98,7 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
|
||||
private void registerCacheAdvisor(Element element, ParserContext parserContext) {
|
||||
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
|
||||
SpringCachingConfigurer.registerCacheAdvisor(element, parserContext);
|
||||
if (jsr107Present && jCacheImplPresent) { // Register JCache advisor
|
||||
if (jsr107Present && jcacheImplPresent) {
|
||||
JCacheCachingConfigurer.registerCacheAdvisor(element, parserContext);
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+16
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,14 +31,16 @@ public abstract class AbstractCacheInvoker {
|
||||
|
||||
private CacheErrorHandler errorHandler;
|
||||
|
||||
|
||||
protected AbstractCacheInvoker() {
|
||||
this(new SimpleCacheErrorHandler());
|
||||
}
|
||||
|
||||
protected AbstractCacheInvoker(CacheErrorHandler errorHandler) {
|
||||
Assert.notNull("ErrorHandler must not be null");
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
protected AbstractCacheInvoker() {
|
||||
this(new SimpleCacheErrorHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link CacheErrorHandler} instance to use to handle errors
|
||||
@@ -56,6 +58,7 @@ public abstract class AbstractCacheInvoker {
|
||||
return this.errorHandler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute {@link Cache#get(Object)} on the specified {@link Cache} and
|
||||
* invoke the error handler if an exception occurs. Return {@code null}
|
||||
@@ -67,9 +70,9 @@ public abstract class AbstractCacheInvoker {
|
||||
try {
|
||||
return cache.get(key);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
getErrorHandler().handleCacheGetError(e, cache, key);
|
||||
return null; // If the exception is handled, return a cache miss
|
||||
catch (RuntimeException ex) {
|
||||
getErrorHandler().handleCacheGetError(ex, cache, key);
|
||||
return null; // If the exception is handled, return a cache miss
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,8 +84,8 @@ public abstract class AbstractCacheInvoker {
|
||||
try {
|
||||
cache.put(key, result);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
getErrorHandler().handleCachePutError(e, cache, key, result);
|
||||
catch (RuntimeException ex) {
|
||||
getErrorHandler().handleCachePutError(ex, cache, key, result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,8 +97,8 @@ public abstract class AbstractCacheInvoker {
|
||||
try {
|
||||
cache.evict(key);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
getErrorHandler().handleCacheEvictError(e, cache, key);
|
||||
catch (RuntimeException ex) {
|
||||
getErrorHandler().handleCacheEvictError(ex, cache, key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,8 +110,8 @@ public abstract class AbstractCacheInvoker {
|
||||
try {
|
||||
cache.clear();
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
getErrorHandler().handleCacheClearError(e, cache);
|
||||
catch (RuntimeException ex) {
|
||||
getErrorHandler().handleCacheClearError(ex, cache);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -444,7 +444,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
|
||||
excluded.add(context);
|
||||
}
|
||||
}
|
||||
catch (VariableNotAvailableException e) {
|
||||
catch (VariableNotAvailableException ex) {
|
||||
// Ignoring failure due to missing result, consider the cache put has to proceed
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+15
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,8 +17,8 @@
|
||||
package org.springframework.cache.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.context.expression.MethodBasedEvaluationContext;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
@@ -38,25 +38,27 @@ import org.springframework.core.ParameterNameDiscoverer;
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author Stephane Nicoll
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
class CacheEvaluationContext extends MethodBasedEvaluationContext {
|
||||
|
||||
private final List<String> unavailableVariables;
|
||||
private final Set<String> unavailableVariables = new HashSet<String>(1);
|
||||
|
||||
CacheEvaluationContext(Object rootObject, Method method, Object[] args,
|
||||
ParameterNameDiscoverer paramDiscoverer) {
|
||||
|
||||
super(rootObject, method, args, paramDiscoverer);
|
||||
this.unavailableVariables = new ArrayList<String>();
|
||||
CacheEvaluationContext(Object rootObject, Method method, Object[] arguments,
|
||||
ParameterNameDiscoverer parameterNameDiscoverer) {
|
||||
|
||||
super(rootObject, method, arguments, parameterNameDiscoverer);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the specified variable name as unavailable for that context. Any expression trying
|
||||
* to access this variable should lead to an exception.
|
||||
* <p>This permits the validation of expressions that could potentially a variable even
|
||||
* when such variable isn't available yet. Any expression trying to use that variable should
|
||||
* therefore fail to evaluate.
|
||||
* Add the specified variable name as unavailable for that context.
|
||||
* Any expression trying to access this variable should lead to an exception.
|
||||
* <p>This permits the validation of expressions that could potentially a
|
||||
* variable even when such variable isn't available yet. Any expression
|
||||
* trying to use that variable should therefore fail to evaluate.
|
||||
*/
|
||||
public void addUnavailableVariable(String name) {
|
||||
this.unavailableVariables.add(name);
|
||||
|
||||
Vendored
+2
-3
@@ -30,9 +30,8 @@ package org.springframework.cache.interceptor;
|
||||
public interface CacheOperationInvoker {
|
||||
|
||||
/**
|
||||
* Invoke the cache operation defined by this instance. Wraps any
|
||||
* exception that is thrown during the invocation in a
|
||||
* {@link ThrowableWrapper}.
|
||||
* Invoke the cache operation defined by this instance. Wraps any exception
|
||||
* that is thrown during the invocation in a {@link ThrowableWrapper}.
|
||||
* @return the result of the operation
|
||||
* @throws ThrowableWrapper if an error occurred while invoking the operation
|
||||
*/
|
||||
|
||||
+6
-1
@@ -102,7 +102,12 @@ public class NoOpCacheManager implements CacheManager {
|
||||
|
||||
@Override
|
||||
public <T> T get(Object key, Callable<T> valueLoader) {
|
||||
return null;
|
||||
try {
|
||||
return valueLoader.call();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new ValueRetrievalException(key, valueLoader, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -127,15 +127,13 @@ public class AnnotatedBeanDefinitionReader {
|
||||
registerBean(annotatedClass, null, (Class<? extends Annotation>[]) null);
|
||||
}
|
||||
|
||||
public void registerBean(Class<?> annotatedClass,
|
||||
@SuppressWarnings("unchecked") Class<? extends Annotation>... qualifiers) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void registerBean(Class<?> annotatedClass, Class<? extends Annotation>... qualifiers) {
|
||||
registerBean(annotatedClass, null, qualifiers);
|
||||
}
|
||||
|
||||
public void registerBean(Class<?> annotatedClass, String name,
|
||||
@SuppressWarnings("unchecked") Class<? extends Annotation>... qualifiers) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
|
||||
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
|
||||
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
|
||||
return;
|
||||
|
||||
+4
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -79,9 +79,10 @@ public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {
|
||||
ScopeMetadata metadata = new ScopeMetadata();
|
||||
if (definition instanceof AnnotatedBeanDefinition) {
|
||||
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
|
||||
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(annDef.getMetadata(), this.scopeAnnotationType);
|
||||
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
|
||||
annDef.getMetadata(), this.scopeAnnotationType);
|
||||
if (attributes != null) {
|
||||
metadata.setScopeName(attributes.getAliasedString("value", this.scopeAnnotationType, definition.getSource()));
|
||||
metadata.setScopeName(attributes.getString("value"));
|
||||
ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
|
||||
if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) {
|
||||
proxyMode = this.defaultProxyMode;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -79,7 +79,7 @@ public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
logger.warn(String.format("%s was imported but no annotations were found " +
|
||||
"having both 'mode' and 'proxyTargetClass' attributes of type " +
|
||||
"AdviceMode and boolean respectively. This means that auto proxy " +
|
||||
"creator registration and configuration may not have occured as " +
|
||||
"creator registration and configuration may not have occurred as " +
|
||||
"intended, and components may not be proxied as expected. Check to " +
|
||||
"ensure that %s has been @Import'ed on the same class where these " +
|
||||
"annotations are declared; otherwise remove the import of %s " +
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
/**
|
||||
* Indicates that a method produces a bean to be managed by the Spring container.
|
||||
@@ -44,15 +45,15 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
*
|
||||
* <h3>Bean Names</h3>
|
||||
*
|
||||
* <p>While a {@link #name() name} attribute is available, the default strategy for
|
||||
* <p>While a {@link #name} attribute is available, the default strategy for
|
||||
* determining the name of a bean is to use the name of the {@code @Bean} method.
|
||||
* This is convenient and intuitive, but if explicit naming is desired, the
|
||||
* {@code name} attribute may be used. Also note that {@code name} accepts an array
|
||||
* of Strings. This is in order to allow for specifying multiple names (i.e., aliases)
|
||||
* for a single bean.
|
||||
* {@code name} attribute (or its alias {@code value}) may be used. Also note
|
||||
* that {@code name} accepts an array of Strings, allowing for multiple names
|
||||
* (i.e. a primary bean name plus one or more aliases) for a single bean.
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Bean(name={"b1","b2"}) // bean available as 'b1' and 'b2', but not 'myBean'
|
||||
* @Bean({"b1", "b2"}) // bean available as 'b1' and 'b2', but not 'myBean'
|
||||
* public MyBean myBean() {
|
||||
* // instantiate and configure MyBean obj
|
||||
* return obj;
|
||||
@@ -78,9 +79,9 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
* <h3>{@code @Bean} Methods in {@code @Configuration} Classes</h3>
|
||||
*
|
||||
* <p>Typically, {@code @Bean} methods are declared within {@code @Configuration}
|
||||
* classes. In this case, bean methods may reference other {@code @Bean} methods
|
||||
* in the same class by calling them <i>directly</i>. This ensures that references between
|
||||
* beans are strongly typed and navigable. Such so-called <em>'inter-bean references'</em> are
|
||||
* classes. In this case, bean methods may reference other {@code @Bean} methods in the
|
||||
* same class by calling them <i>directly</i>. This ensures that references between beans
|
||||
* are strongly typed and navigable. Such so-called <em>'inter-bean references'</em> are
|
||||
* guaranteed to respect scoping and AOP semantics, just like {@code getBean()} lookups
|
||||
* would. These are the semantics known from the original 'Spring JavaConfig' project
|
||||
* which require CGLIB subclassing of each such configuration class at runtime. As a
|
||||
@@ -190,10 +191,24 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
public @interface Bean {
|
||||
|
||||
/**
|
||||
* The name of this bean, or if plural, aliases for this bean. If left unspecified
|
||||
* the name of the bean is the name of the annotated method. If specified, the method
|
||||
* name is ignored.
|
||||
* Alias for {@link #name}.
|
||||
* <p>Intended to be used when no other attributes are needed, for example:
|
||||
* {@code @Bean("customBeanName")}.
|
||||
* @since 4.3.3
|
||||
* @see #name
|
||||
*/
|
||||
@AliasFor("name")
|
||||
String[] value() default {};
|
||||
|
||||
/**
|
||||
* The name of this bean, or if several names, a primary bean name plus aliases.
|
||||
* <p>If left unspecified, the name of the bean is the name of the annotated method.
|
||||
* If specified, the method name is ignored.
|
||||
* <p>The bean name and aliases may also be configured via the {@link #value}
|
||||
* attribute if no other attributes are declared.
|
||||
* @see #value
|
||||
*/
|
||||
@AliasFor("value")
|
||||
String[] name() default {};
|
||||
|
||||
/**
|
||||
|
||||
+11
-40
@@ -25,17 +25,10 @@ import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.Aware;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
@@ -61,16 +54,16 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
class ComponentScanAnnotationParser {
|
||||
|
||||
private final ResourceLoader resourceLoader;
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
private final BeanDefinitionRegistry registry;
|
||||
private final ResourceLoader resourceLoader;
|
||||
|
||||
private final BeanNameGenerator beanNameGenerator;
|
||||
|
||||
private final BeanDefinitionRegistry registry;
|
||||
|
||||
public ComponentScanAnnotationParser(ResourceLoader resourceLoader, Environment environment,
|
||||
|
||||
public ComponentScanAnnotationParser(Environment environment, ResourceLoader resourceLoader,
|
||||
BeanNameGenerator beanNameGenerator, BeanDefinitionRegistry registry) {
|
||||
|
||||
this.resourceLoader = resourceLoader;
|
||||
@@ -90,7 +83,7 @@ class ComponentScanAnnotationParser {
|
||||
scanner.setResourceLoader(this.resourceLoader);
|
||||
|
||||
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
|
||||
boolean useInheritedGenerator = BeanNameGenerator.class == generatorClass;
|
||||
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
|
||||
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
|
||||
BeanUtils.instantiateClass(generatorClass));
|
||||
|
||||
@@ -122,7 +115,7 @@ class ComponentScanAnnotationParser {
|
||||
}
|
||||
|
||||
Set<String> basePackages = new LinkedHashSet<String>();
|
||||
String[] basePackagesArray = componentScan.getAliasedStringArray("basePackages", ComponentScan.class, declaringClass);
|
||||
String[] basePackagesArray = componentScan.getStringArray("basePackages");
|
||||
for (String pkg : basePackagesArray) {
|
||||
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
|
||||
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
|
||||
@@ -148,11 +141,11 @@ class ComponentScanAnnotationParser {
|
||||
List<TypeFilter> typeFilters = new ArrayList<TypeFilter>();
|
||||
FilterType filterType = filterAttributes.getEnum("type");
|
||||
|
||||
for (Class<?> filterClass : filterAttributes.getAliasedClassArray("classes", ComponentScan.Filter.class, null)) {
|
||||
for (Class<?> filterClass : filterAttributes.getClassArray("classes")) {
|
||||
switch (filterType) {
|
||||
case ANNOTATION:
|
||||
Assert.isAssignable(Annotation.class, filterClass,
|
||||
"An error occured while processing a @ComponentScan ANNOTATION type filter: ");
|
||||
"An error occurred while processing a @ComponentScan ANNOTATION type filter: ");
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<Annotation> annotationType = (Class<Annotation>) filterClass;
|
||||
typeFilters.add(new AnnotationTypeFilter(annotationType));
|
||||
@@ -162,9 +155,10 @@ class ComponentScanAnnotationParser {
|
||||
break;
|
||||
case CUSTOM:
|
||||
Assert.isAssignable(TypeFilter.class, filterClass,
|
||||
"An error occured while processing a @ComponentScan CUSTOM type filter: ");
|
||||
"An error occurred while processing a @ComponentScan CUSTOM type filter: ");
|
||||
TypeFilter filter = BeanUtils.instantiateClass(filterClass, TypeFilter.class);
|
||||
invokeAwareMethods(filter);
|
||||
ParserStrategyUtils.invokeAwareMethods(
|
||||
filter, this.environment, this.resourceLoader, this.registry);
|
||||
typeFilters.add(filter);
|
||||
break;
|
||||
default:
|
||||
@@ -188,27 +182,4 @@ class ComponentScanAnnotationParser {
|
||||
return typeFilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke {@link ResourceLoaderAware}, {@link BeanClassLoaderAware} and
|
||||
* {@link BeanFactoryAware} contracts if implemented by the given {@code filter}.
|
||||
*/
|
||||
private void invokeAwareMethods(TypeFilter filter) {
|
||||
if (filter instanceof Aware) {
|
||||
if (filter instanceof EnvironmentAware) {
|
||||
((EnvironmentAware) filter).setEnvironment(this.environment);
|
||||
}
|
||||
if (filter instanceof ResourceLoaderAware) {
|
||||
((ResourceLoaderAware) filter).setResourceLoader(this.resourceLoader);
|
||||
}
|
||||
if (filter instanceof BeanClassLoaderAware) {
|
||||
ClassLoader classLoader = (this.registry instanceof ConfigurableBeanFactory ?
|
||||
((ConfigurableBeanFactory) this.registry).getBeanClassLoader() :
|
||||
this.resourceLoader.getClassLoader());
|
||||
((BeanClassLoaderAware) filter).setBeanClassLoader(classLoader);
|
||||
}
|
||||
if (filter instanceof BeanFactoryAware && this.registry instanceof BeanFactory) {
|
||||
((BeanFactoryAware) filter).setBeanFactory((BeanFactory) this.registry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-10
@@ -84,7 +84,22 @@ import org.springframework.stereotype.Component;
|
||||
* {@code @Configuration} classes are candidates for component scanning (typically using
|
||||
* Spring XML's {@code <context:component-scan/>} element) and therefore may also take
|
||||
* advantage of {@link Autowired @Autowired}/{@link javax.inject.Inject @Inject}
|
||||
* at the field and method level (but not at the constructor level).
|
||||
* like any regular {@code @Component}. In particular, if a single constructor is present
|
||||
* autowiring semantics will be applied transparently:
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
* public class AppConfig {
|
||||
* private final SomeBean someBean;
|
||||
*
|
||||
* public AppConfig(SomeBean someBean) {
|
||||
* this.someBean = someBean;
|
||||
* }
|
||||
*
|
||||
* // @Bean definition using "SomeBean"
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>{@code @Configuration} classes may not only be bootstrapped using
|
||||
* component scanning, but may also themselves <em>configure</em> component scanning using
|
||||
* the {@link ComponentScan @ComponentScan} annotation:
|
||||
@@ -104,13 +119,13 @@ import org.springframework.stereotype.Component;
|
||||
*
|
||||
* Externalized values may be looked up by injecting the Spring
|
||||
* {@link org.springframework.core.env.Environment} into a {@code @Configuration}
|
||||
* class using the {@code @Autowired} or the {@code @Inject} annotation:
|
||||
* class the usual (e.g. using the {@code @Autowired} annotation):
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
* public class AppConfig {
|
||||
*
|
||||
* @Inject Environment env;
|
||||
* @Autowired Environment env;
|
||||
*
|
||||
* @Bean
|
||||
* public MyBean myBean() {
|
||||
@@ -175,7 +190,7 @@ import org.springframework.stereotype.Component;
|
||||
* <p>{@code @Configuration} classes may be composed using the {@link Import @Import} annotation,
|
||||
* not unlike the way that {@code <import>} works in Spring XML. Because
|
||||
* {@code @Configuration} objects are managed as Spring beans within the container,
|
||||
* imported configurations may be injected using {@code @Autowired} or {@code @Inject}:
|
||||
* imported configurations may be injected the usual way (e.g. via constructor injection):
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
@@ -191,7 +206,11 @@ import org.springframework.stereotype.Component;
|
||||
* @Import(DatabaseConfig.class)
|
||||
* public class AppConfig {
|
||||
*
|
||||
* @Inject DatabaseConfig dataConfig;
|
||||
* private final DatabaseConfig dataConfig;
|
||||
*
|
||||
* public AppConfig(DatabaseConfig dataConfig) {
|
||||
* this.dataConfig = dataConfig;
|
||||
* }
|
||||
*
|
||||
* @Bean
|
||||
* public MyBean myBean() {
|
||||
@@ -240,8 +259,8 @@ import org.springframework.stereotype.Component;
|
||||
* As mentioned above, {@code @Configuration} classes may be declared as regular Spring
|
||||
* {@code <bean>} definitions within Spring XML files. It is also possible to
|
||||
* import Spring XML configuration files into {@code @Configuration} classes using
|
||||
* the {@link ImportResource @ImportResource} annotation. Bean definitions imported from XML can be
|
||||
* injected using {@code @Autowired} or {@code @Inject}:
|
||||
* the {@link ImportResource @ImportResource} annotation. Bean definitions imported from
|
||||
* XML can be injected the usual way (e.g. using the {@code Inject} annotation):
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
@@ -340,9 +359,7 @@ import org.springframework.stereotype.Component;
|
||||
* <ul>
|
||||
* <li>@Configuration classes must be non-final
|
||||
* <li>@Configuration classes must be non-local (may not be declared within a method)
|
||||
* <li>@Configuration classes must have a default/no-arg constructor and may not use
|
||||
* {@link Autowired @Autowired} constructor parameters. Any nested configuration classes
|
||||
* must be {@code static}.
|
||||
* <li>Any nested configuration classes must be {@code static}.
|
||||
* </ul>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -233,7 +233,7 @@ final class ConfigurationClass {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ConfigurationClass:beanName=" + this.beanName + ",resource=" + this.resource;
|
||||
return "ConfigurationClass: beanName '" + this.beanName + "', " + this.resource;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -236,7 +236,7 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
|
||||
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
|
||||
if (attributes != null) {
|
||||
beanDef.setScope(attributes.getAliasedString("value", Scope.class, configClass.getResource()));
|
||||
beanDef.setScope(attributes.getString("value"));
|
||||
proxyMode = attributes.getEnum("proxyMode");
|
||||
if (proxyMode == ScopedProxyMode.DEFAULT) {
|
||||
proxyMode = ScopedProxyMode.NO;
|
||||
|
||||
+1
-1
@@ -466,7 +466,7 @@ class ConfigurationClassEnhancer {
|
||||
try {
|
||||
fbProxy = fbClass.newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalStateException("Unable to instantiate enhanced FactoryBean using Objenesis, " +
|
||||
"and regular FactoryBean instantiation via default constructor fails as well", ex);
|
||||
}
|
||||
|
||||
+24
-31
@@ -158,7 +158,7 @@ class ConfigurationClassParser {
|
||||
this.resourceLoader = resourceLoader;
|
||||
this.registry = registry;
|
||||
this.componentScanParser = new ComponentScanAnnotationParser(
|
||||
resourceLoader, environment, componentScanBeanNameGenerator, registry);
|
||||
environment, resourceLoader, componentScanBeanNameGenerator, registry);
|
||||
this.conditionEvaluator = new ConditionEvaluator(registry, environment, resourceLoader);
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ class ConfigurationClassParser {
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new BeanDefinitionStoreException(
|
||||
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
|
||||
}
|
||||
@@ -287,8 +287,9 @@ class ConfigurationClassParser {
|
||||
|
||||
// Process any @ImportResource annotations
|
||||
if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
|
||||
AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
|
||||
String[] resources = importResource.getAliasedStringArray("locations", ImportResource.class, sourceClass);
|
||||
AnnotationAttributes importResource =
|
||||
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
|
||||
String[] resources = importResource.getStringArray("locations");
|
||||
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
|
||||
for (String resource : resources) {
|
||||
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
|
||||
@@ -378,7 +379,7 @@ class ConfigurationClassParser {
|
||||
|
||||
Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
|
||||
PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
|
||||
DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiate(factoryClass));
|
||||
DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
|
||||
|
||||
for (String location : locations) {
|
||||
try {
|
||||
@@ -483,7 +484,7 @@ class ConfigurationClassParser {
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" +
|
||||
configClass.getMetadata().getClassName() + "]", ex);
|
||||
}
|
||||
@@ -497,7 +498,7 @@ class ConfigurationClassParser {
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkForCircularImports && this.importStack.contains(configClass)) {
|
||||
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
|
||||
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
|
||||
}
|
||||
else {
|
||||
@@ -508,7 +509,8 @@ class ConfigurationClassParser {
|
||||
// Candidate class is an ImportSelector -> delegate to it to determine imports
|
||||
Class<?> candidateClass = candidate.loadClass();
|
||||
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
|
||||
invokeAwareMethods(selector);
|
||||
ParserStrategyUtils.invokeAwareMethods(
|
||||
selector, this.environment, this.resourceLoader, this.registry);
|
||||
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
|
||||
this.deferredImportSelectors.add(
|
||||
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
|
||||
@@ -525,7 +527,8 @@ class ConfigurationClassParser {
|
||||
Class<?> candidateClass = candidate.loadClass();
|
||||
ImportBeanDefinitionRegistrar registrar =
|
||||
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
|
||||
invokeAwareMethods(registrar);
|
||||
ParserStrategyUtils.invokeAwareMethods(
|
||||
registrar, this.environment, this.resourceLoader, this.registry);
|
||||
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
|
||||
}
|
||||
else {
|
||||
@@ -540,7 +543,7 @@ class ConfigurationClassParser {
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" +
|
||||
configClass.getMetadata().getClassName() + "]", ex);
|
||||
}
|
||||
@@ -550,28 +553,18 @@ class ConfigurationClassParser {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke {@link ResourceLoaderAware}, {@link BeanClassLoaderAware} and
|
||||
* {@link BeanFactoryAware} contracts if implemented by the given {@code bean}.
|
||||
*/
|
||||
private void invokeAwareMethods(Object importStrategyBean) {
|
||||
if (importStrategyBean instanceof Aware) {
|
||||
if (importStrategyBean instanceof EnvironmentAware) {
|
||||
((EnvironmentAware) importStrategyBean).setEnvironment(this.environment);
|
||||
}
|
||||
if (importStrategyBean instanceof ResourceLoaderAware) {
|
||||
((ResourceLoaderAware) importStrategyBean).setResourceLoader(this.resourceLoader);
|
||||
}
|
||||
if (importStrategyBean instanceof BeanClassLoaderAware) {
|
||||
ClassLoader classLoader = (this.registry instanceof ConfigurableBeanFactory ?
|
||||
((ConfigurableBeanFactory) this.registry).getBeanClassLoader() :
|
||||
this.resourceLoader.getClassLoader());
|
||||
((BeanClassLoaderAware) importStrategyBean).setBeanClassLoader(classLoader);
|
||||
}
|
||||
if (importStrategyBean instanceof BeanFactoryAware && this.registry instanceof BeanFactory) {
|
||||
((BeanFactoryAware) importStrategyBean).setBeanFactory((BeanFactory) this.registry);
|
||||
private boolean isChainedImportOnStack(ConfigurationClass configClass) {
|
||||
if (this.importStack.contains(configClass)) {
|
||||
String configClassName = configClass.getMetadata().getClassName();
|
||||
AnnotationMetadata importingClass = this.importStack.getImportingClassFor(configClassName);
|
||||
while (importingClass != null) {
|
||||
if (configClassName.equals(importingClass.getClassName())) {
|
||||
return true;
|
||||
}
|
||||
importingClass = this.importStack.getImportingClassFor(importingClass.getClassName());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -856,7 +849,7 @@ class ConfigurationClassParser {
|
||||
private SourceClass getRelated(String className) throws IOException {
|
||||
if (this.source instanceof Class<?>) {
|
||||
try {
|
||||
Class<?> clazz = resourceLoader.getClassLoader().loadClass(className);
|
||||
Class<?> clazz = ((Class<?>) this.source).getClassLoader().loadClass(className);
|
||||
return asSourceClass(clazz);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
|
||||
+3
@@ -205,6 +205,9 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
|
||||
this.resourceLoader = resourceLoader;
|
||||
if (!this.setMetadataReaderFactoryCalled) {
|
||||
this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import org.springframework.beans.factory.Aware;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
|
||||
/**
|
||||
* Common delegate code for the handling of parser strategies, e.g.
|
||||
* {@code TypeFilter}, {@code ImportSelector}, {@code ImportBeanDefinitionRegistrar}
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.3.3
|
||||
*/
|
||||
abstract class ParserStrategyUtils {
|
||||
|
||||
/**
|
||||
* Invoke {@link BeanClassLoaderAware}, {@link BeanFactoryAware},
|
||||
* {@link EnvironmentAware}, and {@link ResourceLoaderAware} contracts
|
||||
* if implemented by the given object.
|
||||
*/
|
||||
public static void invokeAwareMethods(Object parserStrategyBean, Environment environment,
|
||||
ResourceLoader resourceLoader, BeanDefinitionRegistry registry) {
|
||||
|
||||
if (parserStrategyBean instanceof Aware) {
|
||||
if (parserStrategyBean instanceof BeanClassLoaderAware) {
|
||||
ClassLoader classLoader = (registry instanceof ConfigurableBeanFactory ?
|
||||
((ConfigurableBeanFactory) registry).getBeanClassLoader() : resourceLoader.getClassLoader());
|
||||
((BeanClassLoaderAware) parserStrategyBean).setBeanClassLoader(classLoader);
|
||||
}
|
||||
if (parserStrategyBean instanceof BeanFactoryAware && registry instanceof BeanFactory) {
|
||||
((BeanFactoryAware) parserStrategyBean).setBeanFactory((BeanFactory) registry);
|
||||
}
|
||||
if (parserStrategyBean instanceof EnvironmentAware) {
|
||||
((EnvironmentAware) parserStrategyBean).setEnvironment(environment);
|
||||
}
|
||||
if (parserStrategyBean instanceof ResourceLoaderAware) {
|
||||
((ResourceLoaderAware) parserStrategyBean).setResourceLoader(resourceLoader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+42
-51
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.context.event;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
@@ -53,6 +52,7 @@ import org.springframework.util.StringUtils;
|
||||
* evaluated prior to invoking the underlying method.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
@@ -70,27 +70,59 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
|
||||
private final List<ResolvableType> declaredEventTypes;
|
||||
|
||||
private final String condition;
|
||||
|
||||
private final int order;
|
||||
|
||||
private final AnnotatedElementKey methodKey;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private EventExpressionEvaluator evaluator;
|
||||
|
||||
private String condition;
|
||||
|
||||
private EventListener eventListener;
|
||||
|
||||
|
||||
public ApplicationListenerMethodAdapter(String beanName, Class<?> targetClass, Method method) {
|
||||
this.beanName = beanName;
|
||||
this.method = method;
|
||||
this.targetClass = targetClass;
|
||||
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
|
||||
this.declaredEventTypes = resolveDeclaredEventTypes();
|
||||
this.methodKey = new AnnotatedElementKey(this.method, this.targetClass);
|
||||
|
||||
EventListener ann = AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class);
|
||||
this.declaredEventTypes = resolveDeclaredEventTypes(method, ann);
|
||||
this.condition = (ann != null ? ann.condition() : null);
|
||||
this.order = resolveOrder(method);
|
||||
|
||||
this.methodKey = new AnnotatedElementKey(method, targetClass);
|
||||
}
|
||||
|
||||
|
||||
private List<ResolvableType> resolveDeclaredEventTypes(Method method, EventListener ann) {
|
||||
int count = method.getParameterTypes().length;
|
||||
if (count > 1) {
|
||||
throw new IllegalStateException(
|
||||
"Maximum one parameter is allowed for event listener method: " + method);
|
||||
}
|
||||
if (ann != null && ann.classes().length > 0) {
|
||||
List<ResolvableType> types = new ArrayList<ResolvableType>(ann.classes().length);
|
||||
for (Class<?> eventType : ann.classes()) {
|
||||
types.add(ResolvableType.forClass(eventType));
|
||||
}
|
||||
return types;
|
||||
}
|
||||
else {
|
||||
if (count == 0) {
|
||||
throw new IllegalStateException(
|
||||
"Event parameter is mandatory for event listener method: " + method);
|
||||
}
|
||||
return Collections.singletonList(ResolvableType.forMethodParameter(method, 0));
|
||||
}
|
||||
}
|
||||
|
||||
private int resolveOrder(Method method) {
|
||||
Order ann = AnnotatedElementUtils.findMergedAnnotation(method, Order.class);
|
||||
return (ann != null ? ann.value() : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this instance.
|
||||
*/
|
||||
@@ -128,8 +160,7 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
Order order = getMethodAnnotation(Order.class);
|
||||
return (order != null ? order.value() : 0);
|
||||
return this.order;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,8 +195,8 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
if (this.method.getParameterTypes().length == 0) {
|
||||
return new Object[0];
|
||||
}
|
||||
if (!ApplicationEvent.class.isAssignableFrom(declaredEventType.getRawClass())
|
||||
&& event instanceof PayloadApplicationEvent) {
|
||||
if (!ApplicationEvent.class.isAssignableFrom(declaredEventType.getRawClass()) &&
|
||||
event instanceof PayloadApplicationEvent) {
|
||||
return new Object[] {((PayloadApplicationEvent) event).getPayload()};
|
||||
}
|
||||
else {
|
||||
@@ -212,10 +243,6 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
return true;
|
||||
}
|
||||
|
||||
protected <A extends Annotation> A getMethodAnnotation(Class<A> annotationType) {
|
||||
return AnnotatedElementUtils.findMergedAnnotation(this.method, annotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the event listener method with the given argument values.
|
||||
*/
|
||||
@@ -253,13 +280,6 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
return this.applicationContext.getBean(this.beanName);
|
||||
}
|
||||
|
||||
protected EventListener getEventListener() {
|
||||
if (this.eventListener == null) {
|
||||
this.eventListener = AnnotatedElementUtils.findMergedAnnotation(this.method, EventListener.class);
|
||||
}
|
||||
return this.eventListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the condition to use.
|
||||
* <p>Matches the {@code condition} attribute of the {@link EventListener}
|
||||
@@ -267,12 +287,6 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
* is meta-annotated with {@code @EventListener}.
|
||||
*/
|
||||
protected String getCondition() {
|
||||
if (this.condition == null) {
|
||||
EventListener eventListener = AnnotatedElementUtils.findMergedAnnotation(this.method, EventListener.class);
|
||||
if (eventListener != null) {
|
||||
this.condition = eventListener.condition();
|
||||
}
|
||||
}
|
||||
return this.condition;
|
||||
}
|
||||
|
||||
@@ -346,29 +360,6 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<ResolvableType> resolveDeclaredEventTypes() {
|
||||
int count = this.method.getParameterTypes().length;
|
||||
if (count > 1) {
|
||||
throw new IllegalStateException(
|
||||
"Maximum one parameter is allowed for event listener method: " + this.method);
|
||||
}
|
||||
EventListener ann = getEventListener();
|
||||
if (ann != null && ann.classes().length > 0) {
|
||||
List<ResolvableType> types = new ArrayList<ResolvableType>();
|
||||
for (Class<?> eventType : ann.classes()) {
|
||||
types.add(ResolvableType.forClass(eventType));
|
||||
}
|
||||
return types;
|
||||
}
|
||||
else {
|
||||
if (count == 0) {
|
||||
throw new IllegalStateException(
|
||||
"Event parameter is mandatory for event listener method: " + this.method);
|
||||
}
|
||||
return Collections.singletonList(ResolvableType.forMethodParameter(this.method, 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
+31
-21
@@ -17,6 +17,7 @@
|
||||
package org.springframework.context.expression;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
@@ -34,26 +35,27 @@ import org.springframework.util.ObjectUtils;
|
||||
* </ol>
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.2
|
||||
*/
|
||||
public class MethodBasedEvaluationContext extends StandardEvaluationContext {
|
||||
|
||||
private final Method method;
|
||||
|
||||
private final Object[] args;
|
||||
private final Object[] arguments;
|
||||
|
||||
private final ParameterNameDiscoverer paramDiscoverer;
|
||||
private final ParameterNameDiscoverer parameterNameDiscoverer;
|
||||
|
||||
private boolean paramLoaded = false;
|
||||
private boolean argumentsLoaded = false;
|
||||
|
||||
|
||||
public MethodBasedEvaluationContext(Object rootObject, Method method, Object[] args,
|
||||
ParameterNameDiscoverer paramDiscoverer) {
|
||||
public MethodBasedEvaluationContext(Object rootObject, Method method, Object[] arguments,
|
||||
ParameterNameDiscoverer parameterNameDiscoverer) {
|
||||
|
||||
super(rootObject);
|
||||
this.method = method;
|
||||
this.args = args;
|
||||
this.paramDiscoverer = paramDiscoverer;
|
||||
this.arguments = arguments;
|
||||
this.parameterNameDiscoverer = parameterNameDiscoverer;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,9 +65,9 @@ public class MethodBasedEvaluationContext extends StandardEvaluationContext {
|
||||
if (variable != null) {
|
||||
return variable;
|
||||
}
|
||||
if (!this.paramLoaded) {
|
||||
if (!this.argumentsLoaded) {
|
||||
lazyLoadArguments();
|
||||
this.paramLoaded = true;
|
||||
this.argumentsLoaded = true;
|
||||
variable = super.lookupVariable(name);
|
||||
}
|
||||
return variable;
|
||||
@@ -75,22 +77,30 @@ public class MethodBasedEvaluationContext extends StandardEvaluationContext {
|
||||
* Load the param information only when needed.
|
||||
*/
|
||||
protected void lazyLoadArguments() {
|
||||
// shortcut if no args need to be loaded
|
||||
if (ObjectUtils.isEmpty(this.args)) {
|
||||
// Shortcut if no args need to be loaded
|
||||
if (ObjectUtils.isEmpty(this.arguments)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// save arguments as indexed variables
|
||||
for (int i = 0; i < this.args.length; i++) {
|
||||
setVariable("a" + i, this.args[i]);
|
||||
setVariable("p" + i, this.args[i]);
|
||||
}
|
||||
// Expose indexed variables as well as parameter names (if discoverable)
|
||||
String[] paramNames = this.parameterNameDiscoverer.getParameterNames(this.method);
|
||||
int paramCount = (paramNames != null ? paramNames.length : this.method.getParameterTypes().length);
|
||||
int argsCount = this.arguments.length;
|
||||
|
||||
String[] parameterNames = this.paramDiscoverer.getParameterNames(this.method);
|
||||
// save parameter names (if discovered)
|
||||
if (parameterNames != null) {
|
||||
for (int i = 0; i < parameterNames.length; i++) {
|
||||
setVariable(parameterNames[i], this.args[i]);
|
||||
for (int i = 0; i < paramCount; i++) {
|
||||
Object value = null;
|
||||
if (argsCount > paramCount && i == paramCount - 1) {
|
||||
// Expose remaining arguments as vararg array for last parameter
|
||||
value = Arrays.copyOfRange(this.arguments, i, argsCount);
|
||||
}
|
||||
else if (argsCount > i) {
|
||||
// Actual argument found - otherwise left as null
|
||||
value = this.arguments[i];
|
||||
}
|
||||
setVariable("a" + i, value);
|
||||
setVariable("p" + i, value);
|
||||
if (paramNames != null) {
|
||||
setVariable(paramNames[i], value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -91,6 +91,8 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
|
||||
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
private boolean customClassLoader = false;
|
||||
|
||||
private final AtomicBoolean refreshed = new AtomicBoolean();
|
||||
|
||||
|
||||
@@ -198,6 +200,10 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// ResourceLoader / ResourcePatternResolver override if necessary
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This implementation delegates to this context's ResourceLoader if set,
|
||||
* falling back to the default superclass behavior else.
|
||||
@@ -225,6 +231,20 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
|
||||
return super.getResources(locationPattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClassLoader(ClassLoader classLoader) {
|
||||
super.setClassLoader(classLoader);
|
||||
this.customClassLoader = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getClassLoader() {
|
||||
if (this.resourceLoader != null && !this.customClassLoader) {
|
||||
return this.resourceLoader.getClassLoader();
|
||||
}
|
||||
return super.getClassLoader();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementations of AbstractApplicationContext's template methods
|
||||
|
||||
+19
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -165,6 +165,9 @@ public class LiveBeansView implements LiveBeansViewMBean, ApplicationContextAwar
|
||||
result.append(",\n");
|
||||
}
|
||||
result.append("{\n\"bean\": \"").append(beanName).append("\",\n");
|
||||
result.append("\"aliases\": ");
|
||||
appendArray(result, bf.getAliases(beanName));
|
||||
result.append(",\n");
|
||||
String scope = bd.getScope();
|
||||
if (!StringUtils.hasText(scope)) {
|
||||
scope = BeanDefinition.SCOPE_SINGLETON;
|
||||
@@ -178,16 +181,9 @@ public class LiveBeansView implements LiveBeansViewMBean, ApplicationContextAwar
|
||||
result.append("\"type\": null,\n");
|
||||
}
|
||||
result.append("\"resource\": \"").append(getEscapedResourceDescription(bd)).append("\",\n");
|
||||
result.append("\"dependencies\": [");
|
||||
String[] dependencies = bf.getDependenciesForBean(beanName);
|
||||
if (dependencies.length > 0) {
|
||||
result.append("\"");
|
||||
}
|
||||
result.append(StringUtils.arrayToDelimitedString(dependencies, "\", \""));
|
||||
if (dependencies.length > 0) {
|
||||
result.append("\"");
|
||||
}
|
||||
result.append("]\n}");
|
||||
result.append("\"dependencies\": ");
|
||||
appendArray(result, bf.getDependenciesForBean(beanName));
|
||||
result.append("\n}");
|
||||
elementAppended = true;
|
||||
}
|
||||
}
|
||||
@@ -241,4 +237,16 @@ public class LiveBeansView implements LiveBeansViewMBean, ApplicationContextAwar
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private void appendArray(StringBuilder result, String[] arr) {
|
||||
result.append('[');
|
||||
if (arr.length > 0) {
|
||||
result.append('\"');
|
||||
}
|
||||
result.append(StringUtils.arrayToDelimitedString(arr, "\", \""));
|
||||
if (arr.length > 0) {
|
||||
result.append('\"');
|
||||
}
|
||||
result.append(']');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -104,7 +104,7 @@ public @interface DateTimeFormat {
|
||||
|
||||
/**
|
||||
* 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-31T01:30:00.000-05:00".
|
||||
* <p>This is the default if no annotation value is specified.
|
||||
*/
|
||||
DATE_TIME,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -191,7 +191,7 @@ public class DateFormatter implements Formatter<Date> {
|
||||
if (timeStyle != -1) {
|
||||
return DateFormat.getTimeInstance(timeStyle, locale);
|
||||
}
|
||||
throw new IllegalStateException("Unsupported style pattern '"+ this.stylePattern+ "'");
|
||||
throw new IllegalStateException("Unsupported style pattern '" + this.stylePattern + "'");
|
||||
|
||||
}
|
||||
return DateFormat.getDateInstance(this.style, locale);
|
||||
|
||||
+4
-2
@@ -18,7 +18,6 @@ package org.springframework.format.support;
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.text.ParseException;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.format.Formatter;
|
||||
@@ -65,7 +64,10 @@ public class FormatterPropertyEditorAdapter extends PropertyEditorSupport {
|
||||
try {
|
||||
setValue(this.formatter.parse(text, LocaleContextHolder.getLocale()));
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
catch (IllegalArgumentException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException("Parse attempt failed for value [" + text + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -17,7 +17,6 @@
|
||||
package org.springframework.format.support;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -193,11 +192,14 @@ public class FormattingConversionService extends GenericConversionService
|
||||
try {
|
||||
result = this.parser.parse(text, LocaleContextHolder.getLocale());
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
catch (IllegalArgumentException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException("Parse attempt failed for value [" + text + "]", ex);
|
||||
}
|
||||
if (result == null) {
|
||||
throw new IllegalStateException("Parsers are not allowed to return null");
|
||||
throw new IllegalStateException("Parsers are not allowed to return null: " + this.parser);
|
||||
}
|
||||
TypeDescriptor resultType = TypeDescriptor.valueOf(result.getClass());
|
||||
if (!resultType.isAssignableTo(targetType)) {
|
||||
|
||||
+2
-2
@@ -26,8 +26,8 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.instrument.classloading.LoadTimeWeaver} implementation for Tomcat's
|
||||
* new {@link org.apache.tomcat.InstrumentableClassLoader InstrumentableClassLoader}.
|
||||
* {@link org.springframework.instrument.classloading.LoadTimeWeaver} implementation
|
||||
* for Tomcat's new {@code org.apache.tomcat.InstrumentableClassLoader}.
|
||||
* Also capable of handling Spring's TomcatInstrumentableClassLoader when encountered.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource, BeanFac
|
||||
if (ann == null) {
|
||||
return null;
|
||||
}
|
||||
T bean = BeanUtils.instantiate(beanClass);
|
||||
T bean = BeanUtils.instantiateClass(beanClass);
|
||||
AnnotationBeanUtils.copyPropertiesToBean(ann, bean);
|
||||
return bean;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user