diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cdde5c729547..3258d9118e18 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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 diff --git a/build.gradle b/build.gradle index e9f47cf2ed02..bd1f4ec032d2 100644 --- a/build.gradle +++ b/build.gradle @@ -32,51 +32,52 @@ configure(allprojects) { project -> version = qualifyVersionIfNecessary(version) ext.aspectjVersion = "1.8.9" - ext.caffeineVersion = "2.3.1" + ext.caffeineVersion = "2.3.5" ext.eclipselinkVersion = "2.4.2" - ext.ehcacheVersion = "2.10.2" + ext.ehcacheVersion = "2.10.4" ext.ehcachejcacheVersion = "1.0.1" - ext.ehcache3Version = "3.1.1" + ext.ehcache3Version = "3.1.4" ext.ejbVersion = "3.0" - ext.fileuploadVersion = "1.3.2" + ext.fileuploadVersion = "1.3.3" ext.freemarkerVersion = "2.3.23" - ext.groovyVersion = "2.4.7" - ext.gsonVersion = "2.7" - ext.guavaVersion = "19.0" + ext.groovyVersion = "2.4.15" + ext.gsonVersion = "2.8.5" + ext.guavaVersion = "20.0" ext.hamcrestVersion = "1.3" ext.hibernate3Version = "3.6.10.Final" ext.hibernate4Version = "4.3.11.Final" - ext.hibernate5Version = "5.2.1.Final" + ext.hibernate5Version = "5.2.10.Final" ext.hibval4Version = "4.3.2.Final" - ext.hibval5Version = "5.2.4.Final" + ext.hibval5Version = "5.2.5.Final" ext.hsqldbVersion = "2.3.4" - ext.httpasyncVersion = "4.1.2" - ext.httpclientVersion = "4.5.2" - ext.jackson2Version = "2.8.1" + ext.httpasyncVersion = "4.1.4" + ext.httpclientVersion = "4.5.6" + ext.jackson2Version = "2.8.11.3" 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.11.v20160721" - ext.jodaVersion = "2.9.4" - ext.jrubyVersion = "1.7.25" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory) + ext.javamailVersion = "1.5.6" + ext.jettyVersion = "9.3.14.v20161028" // as of 9.3.15, Jetty has hard Servlet 3.1 requirement + ext.jetty94Version = "9.4.6.v20170531" // for spring-websocket support, optimized for Jetty 9.4 + ext.jodaVersion = "2.9.9" + ext.jrubyVersion = "1.7.27" // JRuby 9000 primarily supported through JSR-223 (StandardScriptFactory) ext.jtaVersion = "1.2" ext.junitVersion = "4.12" ext.log4jVersion = "1.2.17" - ext.nettyVersion = "4.1.4.Final" + ext.nettyVersion = "4.1.31.Final" ext.okhttpVersion = "2.7.5" - ext.okhttp3Version = "3.4.1" - ext.openjpaVersion = "2.4.1" + ext.okhttp3Version = "3.8.1" + ext.openjpaVersion = "2.4.2" ext.poiVersion = "3.14" ext.reactorVersion = "2.0.8.RELEASE" - ext.romeVersion = "1.6.0" - ext.slf4jVersion = "1.7.21" + ext.romeVersion = "1.7.4" + ext.slf4jVersion = "1.7.25" ext.snakeyamlVersion = "1.17" - ext.snifferVersion = "1.15" + ext.snifferVersion = "1.17" ext.testngVersion = "6.9.10" ext.tiles2Version = "2.2.2" - ext.tiles3Version = "3.0.5" - ext.tomcatVersion = "8.5.4" + ext.tiles3Version = "3.0.8" + ext.tomcatVersion = "8.5.35" ext.tyrusVersion = "1.3.5" // constrained by WebLogic 12.1.3 support - ext.undertowVersion = "1.3.23.Final" + ext.undertowVersion = "1.3.33.Final" ext.xmlunitVersion = "1.6" ext.xstreamVersion = "1.4.9" @@ -110,11 +111,13 @@ configure(allprojects) { project -> compileJava { sourceCompatibility = 1.6 targetCompatibility = 1.6 + options.encoding = 'UTF-8' } compileTestJava { sourceCompatibility = 1.8 targetCompatibility = 1.8 + options.encoding = 'UTF-8' options.compilerArgs += "-parameters" } @@ -200,9 +203,9 @@ configure(allprojects) { project -> "http://ehcache.org/apidocs/${ehcacheVersion}", "http://ehcache.org/apidocs/${ehcache3Version}", "http://quartz-scheduler.org/api/2.2.1/", - "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://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[] } @@ -214,7 +217,6 @@ configure(subprojects - project(":spring-build-src")) { subproject -> configurations { jacoco } - dependencies { jacoco("org.jacoco:org.jacoco.agent:0.7.5.201505241946:runtime") } @@ -248,16 +250,16 @@ configure(subprojects - project(":spring-build-src")) { subproject -> options.links(project.ext.javadocLinks) options.addStringOption('Xdoclint:none', '-quiet') - // suppress warnings due to cross-module @see and @link references; - // note that global 'api' task does display all warnings. + // Suppress warnings due to cross-module @see and @link references. + // Note that global 'api' task does display all warnings. logging.captureStandardError LogLevel.INFO - logging.captureStandardOutput LogLevel.INFO // suppress "## warnings" message + logging.captureStandardOutput LogLevel.INFO // suppress "## warnings" message } task sourcesJar(type: Jar, dependsOn: classes) { classifier = 'sources' from sourceSets.main.allSource - // don't include or exclude anything explicitly by default. See SPR-12085. + // Don't include or exclude anything explicitly by default. See SPR-12085. } task javadocJar(type: Jar) { @@ -273,6 +275,7 @@ configure(subprojects - project(":spring-build-src")) { subproject -> project("spring-build-src") { description = "Exposes gradle buildSrc for IDE support" + apply plugin: "groovy" dependencies { @@ -286,12 +289,11 @@ project("spring-build-src") { project("spring-core") { description = "Spring Core" - // As of Spring 4.0.3, spring-core includes asm 5.x and repackages cglib 3.2, inlining - // both into the spring-core jar. cglib 3.2 itself depends on asm 5.x and is therefore - // further transformed by the JarJar task to depend on org.springframework.asm; this - // avoids including two different copies of asm unnecessarily. - def cglibVersion = "3.2.4" - def objenesisVersion = "2.4" + // spring-core includes asm and repackages cglib, inlining both into the spring-core jar. + // cglib itself depends on asm and is therefore further transformed by the JarJar task to + // depend on org.springframework.asm; this avoids including two different copies of asm. + def cglibVersion = "3.2.6" + def objenesisVersion = "2.6" configurations { jarjar @@ -311,9 +313,9 @@ project("spring-core") { configurations.cglib.each { originalJar -> zipfileset(src: originalJar) } - // repackage net.sf.cglib => org.springframework.cglib + // Repackage net.sf.cglib => org.springframework.cglib rule(pattern: "net.sf.cglib.**", result: "org.springframework.cglib.@1") - // as mentioned above, transform cglib"s internal asm dependencies from + // As mentioned above, transform cglib's internal asm dependencies from // org.objectweb.asm => org.springframework.asm. Doing this counts on the // the fact that Spring and cglib depend on the same version of asm! rule(pattern: "org.objectweb.asm.**", result: "org.springframework.asm.@1") @@ -334,7 +336,7 @@ project("spring-core") { configurations.objenesis.each { originalJar -> zipfileset(src: originalJar) } - // repackage org.objenesis => org.springframework.objenesis + // Repackage org.objenesis => org.springframework.objenesis rule(pattern: "org.objenesis.**", result: "org.springframework.objenesis.@1") } } @@ -351,17 +353,17 @@ project("spring-core") { compile("commons-logging:commons-logging:1.2") optional("commons-codec:commons-codec:1.10") optional("org.aspectj:aspectjweaver:${aspectjVersion}") - optional("net.sf.jopt-simple:jopt-simple:5.0.2") + optional("net.sf.jopt-simple:jopt-simple:5.0.3") optional("log4j:log4j:${log4jVersion}") testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}") testCompile("xmlunit:xmlunit:${xmlunitVersion}") - testCompile("com.fasterxml.woodstox:woodstox-core:5.0.2") { + testCompile("com.fasterxml.woodstox:woodstox-core:5.0.3") { exclude group: "stax", module: "stax-api" } } jar { - // inline repackaged cglib classes directly into the spring-core jar + // Inline repackaged cglib classes directly into spring-core jar dependsOn cglibRepackJar from(zipTree(cglibRepackJar.archivePath)) { include "org/springframework/cglib/**" @@ -390,6 +392,7 @@ project("spring-beans") { project("spring-beans-groovy") { description "Groovy Bean Definitions" + merge.into = project(":spring-beans") apply plugin: "groovy" @@ -398,8 +401,8 @@ project("spring-beans-groovy") { optional("org.codehaus.groovy:groovy-all:${groovyVersion}") } - // this module's Java and Groovy sources need to be compiled together - compileJava.enabled=false + // This module's Java and Groovy sources need to be compiled together. + compileJava.enabled = false sourceSets { main { groovy { @@ -465,26 +468,27 @@ project("spring-instrument-tomcat") { project("spring-context") { description = "Spring Context" + apply plugin: "groovy" dependencies { compile(project(":spring-aop")) compile(project(":spring-beans")) - compile(project(":spring-expression")) compile(project(":spring-core")) + compile(project(":spring-expression")) compile(files(project(":spring-core").cglibRepackJar)) optional(project(":spring-instrument")) 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}") optional("joda-time:joda-time:${jodaVersion}") optional("org.aspectj:aspectjweaver:${aspectjVersion}") optional("org.codehaus.groovy:groovy-all:${groovyVersion}") - optional("org.beanshell:bsh:2.0b4") + optional("org.beanshell:bsh:2.0b5") optional("org.jruby:jruby:${jrubyVersion}") testCompile("javax.inject:javax.inject-tck:1") testCompile("org.javamoney:moneta:1.1") @@ -494,13 +498,44 @@ project("spring-context") { } } +project("spring-oxm") { + description = "Spring Object/XML Marshalling" + apply from: "oxm.gradle" + + dependencies { + compile(project(":spring-beans")) + compile(project(":spring-core")) + optional("org.codehaus.castor:castor-xml:1.4.1") { + exclude group: 'stax', module: 'stax-api' + exclude group: "org.springframework", module: "spring-context" + } + optional("org.apache.xmlbeans:xmlbeans:2.6.0") { + exclude group: 'stax', module: 'stax-api' + } + optional("com.thoughtworks.xstream:xstream:${xstreamVersion}") { + exclude group: 'xpp3', module: 'xpp3_min' + exclude group: 'xmlpull', module: 'xmlpull' + } + optional("org.jibx:jibx-run:1.2.6") + testCompile(project(":spring-context")) + testCompile("org.ogce:xpp3:1.1.6") + testCompile("org.codehaus.jettison:jettison:1.3.8") { + exclude group: 'stax', module: 'stax-api' + } + testCompile("xmlunit:xmlunit:${xmlunitVersion}") + testCompile(files(genCastor.classesDir).builtBy(genCastor)) + testCompile(files(genJaxb.classesDir).builtBy(genJaxb)) + testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans)) + } +} + project("spring-messaging") { description = "Spring Messaging" dependencies { compile(project(":spring-beans")) - compile(project(":spring-core")) compile(project(":spring-context")) + compile(project(":spring-core")) optional(project(":spring-oxm")) optional("io.projectreactor:reactor-core:${reactorVersion}") optional("io.projectreactor:reactor-net:${reactorVersion}") { @@ -552,45 +587,14 @@ project("spring-tx") { } } -project("spring-oxm") { - description = "Spring Object/XML Marshalling" - apply from: "oxm.gradle" - - dependencies { - compile(project(":spring-beans")) - compile(project(":spring-core")) - optional("org.codehaus.castor:castor-xml:1.4.1") { - exclude group: 'stax', module: 'stax-api' - exclude group: "org.springframework", module: "spring-context" - } - optional("org.apache.xmlbeans:xmlbeans:2.6.0") { - exclude group: 'stax', module: 'stax-api' - } - optional("com.thoughtworks.xstream:xstream:${xstreamVersion}") { - exclude group: 'xpp3', module: 'xpp3_min' - exclude group: 'xmlpull', module: 'xmlpull' - } - optional("org.jibx:jibx-run:1.2.6") - testCompile(project(":spring-context")) - testCompile("xmlunit:xmlunit:${xmlunitVersion}") - testCompile("xpp3:xpp3:1.1.4c") - testCompile("org.codehaus.jettison:jettison:1.3.7") { - exclude group: 'stax', module: 'stax-api' - } - testCompile(files(genCastor.classesDir).builtBy(genCastor)) - testCompile(files(genJaxb.classesDir).builtBy(genJaxb)) - testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans)) - } -} - project("spring-jms") { description = "Spring JMS" dependencies { - compile(project(":spring-core")) - compile(project(":spring-beans")) compile(project(":spring-aop")) + compile(project(":spring-beans")) compile(project(":spring-context")) + compile(project(":spring-core")) compile(project(":spring-messaging")) compile(project(":spring-tx")) provided("javax.jms:jms-api:1.1-rev-1") @@ -612,9 +616,9 @@ project("spring-jdbc") { optional("javax.transaction:javax.transaction-api:${jtaVersion}") optional("com.mchange:c3p0:0.9.5.2") optional("org.hsqldb:hsqldb:${hsqldbVersion}") - optional("com.h2database:h2:1.4.192") - optional("org.apache.derby:derby:10.12.1.1") - optional("org.apache.derby:derbyclient:10.12.1.1") + optional("com.h2database:h2:1.4.193") + optional("org.apache.derby:derby:10.13.1.1") + optional("org.apache.derby:derbyclient:10.13.1.1") } } @@ -622,9 +626,9 @@ project("spring-context-support") { description = "Spring Context Support" dependencies { - compile(project(":spring-core")) compile(project(":spring-beans")) compile(project(":spring-context")) + compile(project(":spring-core")) optional(project(":spring-jdbc")) // for Quartz support optional(project(":spring-tx")) // for Quartz support optional("javax.mail:javax.mail-api:${javamailVersion}") @@ -653,11 +657,14 @@ project("spring-context-support") { testCompile("org.slf4j:slf4j-api:${slf4jVersion}") testRuntime("com.sun.mail:javax.mail:${javamailVersion}") testRuntime("org.ehcache:jcache:${ehcachejcacheVersion}") + testRuntime("org.ehcache:ehcache:${ehcache3Version}") + testRuntime("org.terracotta:management-model:2.3.0") } } project("spring-web") { description = "Spring Web" + apply plugin: "groovy" // Re-generate Protobuf classes from *.proto files and move them in test sources @@ -696,7 +703,7 @@ project("spring-web") { optional("com.squareup.okhttp:okhttp:${okhttpVersion}") optional("com.squareup.okhttp3:okhttp:${okhttp3Version}") optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}") - optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:${jackson2Version}") + optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.8.11") optional("com.google.code.gson:gson:${gsonVersion}") optional("com.rometools:rome:${romeVersion}") optional("org.eclipse.jetty:jetty-servlet:${jettyVersion}") { @@ -712,12 +719,14 @@ project("spring-web") { testCompile(project(":spring-context-support")) // for JafMediaTypeFactory testCompile("xmlunit:xmlunit:${xmlunitVersion}") testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}") + testCompile("org.skyscreamer:jsonassert:1.4.0") testCompile("org.apache.taglibs:taglibs-standard-jstlel:1.2.1") { exclude group: "org.apache.taglibs", module: "taglibs-standard-spec" } - testCompile("com.fasterxml.jackson.datatype:jackson-datatype-joda:${jackson2Version}") - testCompile("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:${jackson2Version}") - testCompile("com.fasterxml.jackson.module:jackson-module-kotlin:${jackson2Version}") + testCompile("com.fasterxml.jackson.datatype:jackson-datatype-joda:2.8.11") + testCompile("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.8.11") + testCompile("com.fasterxml.jackson.module:jackson-module-kotlin:2.8.11.1") + testCompile("com.squareup.okhttp3:mockwebserver:${okhttp3Version}") testRuntime("com.sun.mail:javax.mail:${javamailVersion}") } } @@ -827,7 +836,7 @@ project("spring-webmvc") { exclude group: "org.springframework", module: "spring-context" } optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}") - optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:${jackson2Version}") + optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.8.11") optional("com.rometools:rome:${romeVersion}") optional("javax.el:javax.el-api:2.2.5") optional("org.apache.tiles:tiles-api:${tiles3Version}") @@ -847,7 +856,7 @@ project("spring-webmvc") { exclude group: "org.slf4j", module: "jcl-over-slf4j" exclude group: "org.springframework", module: "spring-web" } - optional('org.webjars:webjars-locator:0.32') + optional('org.webjars:webjars-locator:0.32-1') testCompile("xmlunit:xmlunit:${xmlunitVersion}") testCompile("dom4j:dom4j:1.6.1") { exclude group: "xml-apis", module: "xml-apis" @@ -867,10 +876,10 @@ project("spring-webmvc") { testCompile("org.hibernate:hibernate-validator:${hibval4Version}") testCompile("org.apache.httpcomponents:httpclient:${httpclientVersion}") testCompile("commons-fileupload:commons-fileupload:${fileuploadVersion}") - testCompile("commons-io:commons-io:1.3") + testCompile("commons-io:commons-io:1.4") testCompile("joda-time:joda-time:${jodaVersion}") testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}") - testCompile("org.mozilla:rhino:1.7.7.1") + testCompile("org.mozilla:rhino:1.7.7.2") testRuntime("org.jruby:jruby:${jrubyVersion}") testRuntime("org.python:jython-standalone:2.5.3") testRuntime("org.webjars:underscorejs:1.8.3") @@ -928,8 +937,8 @@ project("spring-websocket") { description = "Spring WebSocket" dependencies { - compile(project(":spring-core")) compile(project(":spring-context")) + compile(project(":spring-core")) compile(project(":spring-web")) optional(project(":spring-messaging")) optional(project(":spring-webmvc")) @@ -946,11 +955,11 @@ project("spring-websocket") { optional("org.eclipse.jetty:jetty-webapp:${jettyVersion}") { exclude group: "javax.servlet", module: "javax.servlet" } - optional("org.eclipse.jetty.websocket:websocket-server:${jettyVersion}") { + optional("org.eclipse.jetty.websocket:websocket-server:${jetty94Version}") { exclude group: "javax.servlet", module: "javax.servlet" } - optional("org.eclipse.jetty.websocket:websocket-client:${jettyVersion}") - optional("org.eclipse.jetty:jetty-client:${jettyVersion}") + optional("org.eclipse.jetty.websocket:websocket-client:${jetty94Version}") + optional("org.eclipse.jetty:jetty-client:${jetty94Version}") optional("io.undertow:undertow-core:${undertowVersion}") optional("io.undertow:undertow-servlet:${undertowVersion}") { exclude group: "org.jboss.spec.javax.servlet", module: "jboss-servlet-api_3.1_spec" @@ -974,11 +983,12 @@ project("spring-test") { dependencies { compile(project(":spring-core")) + optional(project(":spring-aop")) optional(project(":spring-beans")) optional(project(":spring-context")) optional(project(":spring-jdbc")) - optional(project(":spring-tx")) optional(project(":spring-orm")) + optional(project(":spring-tx")) optional(project(":spring-web")) optional(project(":spring-webmvc")) optional(project(":spring-webmvc-portlet")) @@ -999,11 +1009,11 @@ project("spring-test") { optional("org.codehaus.groovy:groovy-all:${groovyVersion}") optional("org.hamcrest:hamcrest-core:${hamcrestVersion}") optional("xmlunit:xmlunit:${xmlunitVersion}") - optional("net.sourceforge.htmlunit:htmlunit:2.22") - optional("org.seleniumhq.selenium:htmlunit-driver:2.21") + optional("net.sourceforge.htmlunit:htmlunit:2.23") + optional("org.seleniumhq.selenium:htmlunit-driver:2.23.2") optional("org.seleniumhq.selenium:selenium-java:2.53.1") - optional("org.skyscreamer:jsonassert:1.3.0") - optional("com.jayway.jsonpath:json-path:2.2.0") + optional("org.skyscreamer:jsonassert:1.4.0") + optional("com.jayway.jsonpath:json-path:2.3.0") testCompile(project(":spring-context-support")) testCompile(project(":spring-oxm")) testCompile("javax.mail:javax.mail-api:${javamailVersion}") @@ -1026,8 +1036,6 @@ project("spring-test") { testCompile("org.apache.httpcomponents:httpclient:${httpclientVersion}") testCompile("javax.cache:cache-api:1.0.0") testRuntime("log4j:log4j:${log4jVersion}") - testRuntime("org.ehcache:ehcache:${ehcache3Version}") - testRuntime("org.terracotta:management-model:2.0.0") } task testNG(type: Test) { @@ -1172,7 +1180,7 @@ configure(rootProject) { // don't publish the default jar for the root project configurations.archives.artifacts.clear() - dependencies { // for integration tests + dependencies { // for integration tests testCompile(project(":spring-aop")) testCompile(project(":spring-beans")) testCompile(project(":spring-context")) @@ -1221,11 +1229,11 @@ configure(rootProject) { doFirst { classpath = files( - // ensure Servlet 3.x and Hibernate 4.x have precedence on the javadoc + // Ensure Servlet 3.x and Hibernate 4.x have precedence on the javadoc // classpath over their respective 2.5 and 3.x variants project(":spring-webmvc").sourceSets.main.compileClasspath.files.find { it =~ "servlet-api" }, rootProject.sourceSets.test.compileClasspath.files.find { it =~ "hibernate-core" }, - // ensure the javadoc process can resolve types compiled from .aj sources + // Ensure the javadoc process can resolve types compiled from .aj sources project(":spring-aspects").sourceSets.main.output ) classpath += files(subprojects.collect { it.sourceSets.main.compileClasspath }) @@ -1358,7 +1366,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" diff --git a/gradle.properties b/gradle.properties index b61eae0b3b5f..08f289efc861 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=4.3.2.BUILD-SNAPSHOT +version=4.3.21.RELEASE diff --git a/gradle/publish-maven.gradle b/gradle/publish-maven.gradle index 1145e112a661..eff54387f693 100644 --- a/gradle/publish-maven.gradle +++ b/gradle/publish-maven.gradle @@ -29,8 +29,8 @@ def customizePom(pom, gradleProject) { } licenses { license { - name "The Apache Software License, Version 2.0" - url "http://www.apache.org/licenses/LICENSE-2.0.txt" + name "Apache License, Version 2.0" + url "http://www.apache.org/licenses/LICENSE-2.0" distribution "repo" } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index ca78035ef050..3baa851b28c6 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fc60887c40df..19e5389604fc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -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 diff --git a/spring-aop/src/main/java/org/springframework/aop/MethodMatcher.java b/spring-aop/src/main/java/org/springframework/aop/MethodMatcher.java index 7cba7648cf43..8b528021882a 100644 --- a/spring-aop/src/main/java/org/springframework/aop/MethodMatcher.java +++ b/spring-aop/src/main/java/org/springframework/aop/MethodMatcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,10 +48,11 @@ public interface MethodMatcher { /** - * Perform static checking whether the given method matches. If this - * returns {@code false} or if the {@link #isRuntime()} method - * returns {@code false}, no runtime check (i.e. no. - * {@link #matches(java.lang.reflect.Method, Class, Object[])} call) will be made. + * Perform static checking whether the given method matches. + *
If this returns {@code false} or if the {@link #isRuntime()} + * method returns {@code false}, no runtime check (i.e. no + * {@link #matches(java.lang.reflect.Method, Class, Object[])} call) + * will be made. * @param method the candidate method * @param targetClass the target class (may be {@code null}, in which case * the candidate class must be taken to be the method's declaring class) diff --git a/spring-aop/src/main/java/org/springframework/aop/TargetSource.java b/spring-aop/src/main/java/org/springframework/aop/TargetSource.java index 8e5ccc1fa6c5..f23e16f38dbe 100644 --- a/spring-aop/src/main/java/org/springframework/aop/TargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/TargetSource.java @@ -1,5 +1,5 @@ /*< - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,9 +34,8 @@ public interface TargetSource extends TargetClassAware { /** * Return the type of targets returned by this {@link TargetSource}. - *
Can return {@code null}, although certain usages of a - * {@code TargetSource} might just work with a predetermined - * target class. + *
Can return {@code null}, although certain usages of a {@code TargetSource} + * might just work with a predetermined target class. * @return the type of targets returned by this {@link TargetSource} */ @Override @@ -44,9 +43,8 @@ public interface TargetSource extends TargetClassAware { /** * Will all calls to {@link #getTarget()} return the same object? - *
In that case, there will be no need to invoke - * {@link #releaseTarget(Object)}, and the AOP framework can cache - * the return value of {@link #getTarget()}. + *
In that case, there will be no need to invoke {@link #releaseTarget(Object)}, + * and the AOP framework can cache the return value of {@link #getTarget()}. * @return {@code true} if the target is immutable * @see #getTarget */ @@ -55,14 +53,15 @@ public interface TargetSource extends TargetClassAware { /** * Return a target instance. Invoked immediately before the * AOP framework calls the "target" of an AOP method invocation. - * @return the target object, which contains the joinpoint + * @return the target object which contains the joinpoint, + * or {@code null} if there is no actual target instance * @throws Exception if the target object can't be resolved */ Object getTarget() throws Exception; /** * Release the given target object obtained from the - * {@link #getTarget()} method. + * {@link #getTarget()} method, if any. * @param target object obtained from a call to {@link #getTarget()} * @throws Exception if the object can't be released */ diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java index c75751688998..898602433d65 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -103,8 +103,8 @@ public static JoinPoint currentJoinPoint() { private final AspectInstanceFactory aspectInstanceFactory; /** - * The name of the aspect (ref bean) in which this advice was defined (used - * when determining advice precedence so that we can determine + * The name of the aspect (ref bean) in which this advice was defined + * (used when determining advice precedence so that we can determine * whether two pieces of advice come from the same aspect). */ private String aspectName; @@ -118,13 +118,13 @@ public static JoinPoint currentJoinPoint() { * This will be non-null if the creator of this advice object knows the argument names * and sets them explicitly */ - private String[] argumentNames = null; + private String[] argumentNames; /** Non-null if after throwing advice binds the thrown value */ - private String throwingName = null; + private String throwingName; /** Non-null if after returning advice binds the return value */ - private String returningName = null; + private String returningName; private Class> discoveredReturningType = Object.class; @@ -227,7 +227,7 @@ public String getAspectName() { } /** - * Sets the declaration order of this advice within the aspect + * Set the declaration order of this advice within the aspect. */ public void setDeclarationOrder(int order) { this.declarationOrder = order; @@ -295,8 +295,8 @@ protected void setReturningNameNoCheck(String name) { } catch (Throwable ex) { throw new IllegalArgumentException("Returning name '" + name + - "' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " + - "Root cause: " + ex); + "' is neither a valid argument name nor the fully-qualified " + + "name of a Java type on the classpath. Root cause: " + ex); } } } @@ -329,8 +329,8 @@ protected void setThrowingNameNoCheck(String name) { } catch (Throwable ex) { throw new IllegalArgumentException("Throwing name '" + name + - "' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " + - "Root cause: " + ex); + "' is neither a valid argument name nor the fully-qualified " + + "name of a Java type on the classpath. Root cause: " + ex); } } } @@ -366,7 +366,7 @@ private boolean isVariableName(String name) { * to which argument name. There are multiple strategies for determining * this binding, which are arranged in a ChainOfResponsibility. */ - public synchronized final void calculateArgumentBindings() { + public final synchronized void calculateArgumentBindings() { // The simple case... nothing to bind. if (this.argumentsIntrospected || this.parameterTypes.length == 0) { return; @@ -374,10 +374,8 @@ public synchronized final void calculateArgumentBindings() { int numUnboundArgs = this.parameterTypes.length; Class>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes(); - if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) { - numUnboundArgs--; - } - else if (maybeBindJoinPointStaticPart(parameterTypes[0])) { + if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0]) || + maybeBindJoinPointStaticPart(parameterTypes[0])) { numUnboundArgs--; } diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java index 671951324b2c..fa044c178a3d 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -113,6 +113,7 @@ * returning {@code null} in the case that the parameter names cannot be discovered. * * @author Adrian Colyer + * @author Juergen Hoeller * @since 2.0 */ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscoverer { @@ -154,23 +155,17 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov } + /** The pointcut expression associated with the advice, as a simple String */ + private String pointcutExpression; + private boolean raiseExceptions; - /** - * If the advice is afterReturning, and binds the return value, this is the parameter name used. - */ + /** If the advice is afterReturning, and binds the return value, this is the parameter name used */ private String returningName; - /** - * If the advice is afterThrowing, and binds the thrown value, this is the parameter name used. - */ + /** If the advice is afterThrowing, and binds the thrown value, this is the parameter name used */ private String throwingName; - /** - * The pointcut expression associated with the advice, as a simple String. - */ - private String pointcutExpression; - private Class>[] argumentTypes; private String[] parameterNameBindings; @@ -186,6 +181,7 @@ public AspectJAdviceParameterNameDiscoverer(String pointcutExpression) { this.pointcutExpression = pointcutExpression; } + /** * Indicate whether {@link IllegalArgumentException} and {@link AmbiguousBindingException} * must be thrown as appropriate in the case of failing to deduce advice parameter names. @@ -213,6 +209,7 @@ public void setThrowingName(String throwingName) { this.throwingName = throwingName; } + /** * Deduce the parameter names for an advice method. *
See the {@link AspectJAdviceParameterNameDiscoverer class level javadoc} @@ -418,7 +415,7 @@ private void maybeBindAnnotationsFromPointcutExpression() { String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " "); for (int i = 0; i < tokens.length; i++) { String toMatch = tokens[i]; - int firstParenIndex = toMatch.indexOf("("); + int firstParenIndex = toMatch.indexOf('('); if (firstParenIndex != -1) { toMatch = toMatch.substring(0, firstParenIndex); } @@ -474,7 +471,7 @@ else if (numAnnotationSlots == 1) { * If the token starts meets Java identifier conventions, it's in. */ private String maybeExtractVariableName(String candidateToken) { - if (candidateToken == null || candidateToken.equals("")) { + if (!StringUtils.hasLength(candidateToken)) { return null; } if (Character.isJavaIdentifierStart(candidateToken.charAt(0)) && @@ -578,7 +575,7 @@ private void maybeBindReferencePointcutParameter() { if (toMatch.startsWith("!")) { toMatch = toMatch.substring(1); } - int firstParenIndex = toMatch.indexOf("("); + int firstParenIndex = toMatch.indexOf('('); if (firstParenIndex != -1) { toMatch = toMatch.substring(0, firstParenIndex); } diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java index 3cb261368909..84788bc64309 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,6 @@ import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.aspectj.weaver.BCException; import org.aspectj.weaver.patterns.NamePattern; import org.aspectj.weaver.reflect.ReflectionWorld.ReflectionWorldException; import org.aspectj.weaver.reflect.ShadowMatchImpl; @@ -187,13 +186,24 @@ private void checkReadyToMatch() { throw new IllegalStateException("Must set property 'expression' before attempting to match"); } if (this.pointcutExpression == null) { - this.pointcutClassLoader = (this.beanFactory instanceof ConfigurableBeanFactory ? - ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() : - ClassUtils.getDefaultClassLoader()); + this.pointcutClassLoader = determinePointcutClassLoader(); this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader); } } + /** + * Determine the ClassLoader to use for pointcut evaluation. + */ + private ClassLoader determinePointcutClassLoader() { + if (this.beanFactory instanceof ConfigurableBeanFactory) { + return ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader(); + } + if (this.pointcutDeclarationScope != null) { + return this.pointcutDeclarationScope.getClassLoader(); + } + return ClassUtils.getDefaultClassLoader(); + } + /** * Build the underlying AspectJ pointcut expression. */ @@ -258,7 +268,7 @@ public boolean matches(Class> targetClass) { } } } - catch (BCException ex) { + catch (Throwable ex) { logger.debug("PointcutExpression matching rejected target class", ex); } return false; @@ -326,7 +336,6 @@ public boolean matches(Method method, Class> targetClass, Object... args) { } catch (IllegalStateException ex) { // No current invocation... - // TODO: Should we really proceed here? if (logger.isDebugEnabled()) { logger.debug("Could not access current invocation - matching with limited context: " + ex); } @@ -413,39 +422,46 @@ private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) { shadowMatch = this.shadowMatchCache.get(targetMethod); if (shadowMatch == null) { try { - shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch); - } - catch (ReflectionWorldException ex) { - // Failed to introspect target method, probably because it has been loaded - // in a special ClassLoader. Let's try the declaring ClassLoader instead... - try { - fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass()); - if (fallbackExpression != null) { - shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch); - } - } - catch (ReflectionWorldException ex2) { - fallbackExpression = null; - } - } - if (shadowMatch == null && targetMethod != originalMethod) { - methodToMatch = originalMethod; try { shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch); } - catch (ReflectionWorldException ex3) { - // Could neither introspect the target class nor the proxy class -> - // let's try the original method's declaring class before we give up... + catch (ReflectionWorldException ex) { + // Failed to introspect target method, probably because it has been loaded + // in a special ClassLoader. Let's try the declaring ClassLoader instead... try { fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass()); if (fallbackExpression != null) { shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch); } } - catch (ReflectionWorldException ex4) { + catch (ReflectionWorldException ex2) { fallbackExpression = null; } } + if (shadowMatch == null && targetMethod != originalMethod) { + methodToMatch = originalMethod; + try { + shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch); + } + catch (ReflectionWorldException ex3) { + // Could neither introspect the target class nor the proxy class -> + // let's try the original method's declaring class before we give up... + try { + fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass()); + if (fallbackExpression != null) { + shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch); + } + } + catch (ReflectionWorldException ex4) { + fallbackExpression = null; + } + } + } + } + catch (Throwable ex) { + // Possibly AspectJ 1.8.10 encountering an invalid signature + logger.debug("PointcutExpression matching rejected target method", ex); + fallbackExpression = null; } if (shadowMatch == null) { shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null); diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcutAdvisor.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcutAdvisor.java index 9de941958c74..1c8975419546 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcutAdvisor.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcutAdvisor.java @@ -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. @@ -18,6 +18,8 @@ import org.springframework.aop.Pointcut; import org.springframework.aop.support.AbstractGenericPointcutAdvisor; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; /** * Spring AOP Advisor that can be used for any AspectJ pointcut expression. @@ -26,16 +28,11 @@ * @since 2.0 */ @SuppressWarnings("serial") -public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdvisor { +public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdvisor implements BeanFactoryAware { private final AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); - @Override - public Pointcut getPointcut() { - return this.pointcut; - } - public void setExpression(String expression) { this.pointcut.setExpression(expression); } @@ -52,12 +49,22 @@ public String getLocation() { return this.pointcut.getLocation(); } - public void setParameterTypes(Class>[] types) { + public void setParameterNames(String... names) { + this.pointcut.setParameterNames(names); + } + + public void setParameterTypes(Class>... types) { this.pointcut.setParameterTypes(types); } - public void setParameterNames(String... names) { - this.pointcut.setParameterNames(names); + @Override + public void setBeanFactory(BeanFactory beanFactory) { + this.pointcut.setBeanFactory(beanFactory); + } + + @Override + public Pointcut getPointcut() { + return this.pointcut; } } diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJPointcutAdvisor.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJPointcutAdvisor.java index 14ad6c67a91d..64ead7b69b31 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJPointcutAdvisor.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJPointcutAdvisor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,6 @@ import org.springframework.aop.PointcutAdvisor; import org.springframework.core.Ordered; import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; /** * AspectJPointcutAdvisor that adapts an {@link AbstractAspectJAdvice} @@ -51,11 +50,11 @@ public AspectJPointcutAdvisor(AbstractAspectJAdvice advice) { this.pointcut = advice.buildSafePointcut(); } + public void setOrder(int order) { this.order = order; } - @Override public boolean isPerInstance() { return true; @@ -91,12 +90,12 @@ public boolean equals(Object other) { return false; } AspectJPointcutAdvisor otherAdvisor = (AspectJPointcutAdvisor) other; - return (ObjectUtils.nullSafeEquals(this.advice, otherAdvisor.advice)); + return this.advice.equals(otherAdvisor.advice); } @Override public int hashCode() { - return AspectJPointcutAdvisor.class.hashCode(); + return AspectJPointcutAdvisor.class.hashCode() * 29 + this.advice.hashCode(); } } diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/DeclareParentsAdvisor.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/DeclareParentsAdvisor.java index 47e461551ba7..0c7b05d0d53f 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/DeclareParentsAdvisor.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/DeclareParentsAdvisor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import org.springframework.aop.ClassFilter; import org.springframework.aop.IntroductionAdvisor; +import org.springframework.aop.IntroductionInterceptor; import org.springframework.aop.support.ClassFilters; import org.springframework.aop.support.DelegatePerTargetObjectIntroductionInterceptor; import org.springframework.aop.support.DelegatingIntroductionInterceptor; @@ -34,12 +35,12 @@ */ public class DeclareParentsAdvisor implements IntroductionAdvisor { + private final Advice advice; + private final Class> introducedInterface; private final ClassFilter typePatternClassFilter; - private final Advice advice; - /** * Create a new advisor for this DeclareParents field. @@ -48,8 +49,8 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor { * @param defaultImpl the default implementation class */ public DeclareParentsAdvisor(Class> interfaceType, String typePattern, Class> defaultImpl) { - this(interfaceType, typePattern, defaultImpl, - new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType)); + this(interfaceType, typePattern, + new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType)); } /** @@ -59,8 +60,7 @@ public DeclareParentsAdvisor(Class> interfaceType, String typePattern, Class * @param delegateRef the delegate implementation object */ public DeclareParentsAdvisor(Class> interfaceType, String typePattern, Object delegateRef) { - this(interfaceType, typePattern, delegateRef.getClass(), - new DelegatingIntroductionInterceptor(delegateRef)); + this(interfaceType, typePattern, new DelegatingIntroductionInterceptor(delegateRef)); } /** @@ -68,23 +68,21 @@ public DeclareParentsAdvisor(Class> interfaceType, String typePattern, Object * (cannot use method such as init() to share common code, due the use of final fields) * @param interfaceType static field defining the introduction * @param typePattern type pattern the introduction is restricted to - * @param implementationClass implementation class - * @param advice delegation advice + * @param interceptor the delegation advice as {@link IntroductionInterceptor} */ - private DeclareParentsAdvisor(Class> interfaceType, String typePattern, Class> implementationClass, Advice advice) { + private DeclareParentsAdvisor(Class> interfaceType, String typePattern, IntroductionInterceptor interceptor) { + this.advice = interceptor; this.introducedInterface = interfaceType; - ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern); // Excludes methods implemented. + ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern); ClassFilter exclusion = new ClassFilter() { @Override public boolean matches(Class> clazz) { - return !(introducedInterface.isAssignableFrom(clazz)); + return !introducedInterface.isAssignableFrom(clazz); } }; - this.typePatternClassFilter = ClassFilters.intersection(typePatternFilter, exclusion); - this.advice = advice; } diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPoint.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPoint.java index d6e43ec1fd13..fc606b21fc87 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPoint.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,17 +32,15 @@ import org.springframework.util.Assert; /** - * Implementation of AspectJ ProceedingJoinPoint interface - * wrapping an AOP Alliance MethodInvocation. + * An implementation of the AspectJ {@link ProceedingJoinPoint} interface + * wrapping an AOP Alliance {@link org.aopalliance.intercept.MethodInvocation}. * - *
Note: the {@code getThis()} method returns the current Spring AOP proxy. + *
Note: The {@code getThis()} method returns the current Spring AOP proxy. * The {@code getTarget()} method returns the current Spring AOP target (which may be - * {@code null} if there is no target), and is a plain POJO without any advice. - * If you want to call the object and have the advice take effect, use - * {@code getThis()}. A common example is casting the object to an - * introduced interface in the implementation of an introduction. - * - *
Of course there is no such distinction between target and proxy in AspectJ. + * {@code null} if there is no target instance) as a plain POJO without any advice. + * If you want to call the object and have the advice take effect, use {@code getThis()}. + * A common example is casting the object to an introduced interface in the implementation of + * an introduction. There is no such distinction between target and proxy in AspectJ itself. * * @author Rod Johnson * @author Juergen Hoeller @@ -56,7 +54,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint, private final ProxyMethodInvocation methodInvocation; - private Object[] defensiveCopyOfArgs; + private Object[] args; /** Lazily initialized signature object */ private Signature signature; @@ -75,6 +73,7 @@ public MethodInvocationProceedingJoinPoint(ProxyMethodInvocation methodInvocatio this.methodInvocation = methodInvocation; } + @Override public void set$AroundClosure(AroundClosure aroundClosure) { throw new UnsupportedOperationException(); @@ -115,12 +114,10 @@ public Object getTarget() { @Override public Object[] getArgs() { - if (this.defensiveCopyOfArgs == null) { - Object[] argsSource = this.methodInvocation.getArguments(); - this.defensiveCopyOfArgs = new Object[argsSource.length]; - System.arraycopy(argsSource, 0, this.defensiveCopyOfArgs, 0, argsSource.length); + if (this.args == null) { + this.args = this.methodInvocation.getArguments().clone(); } - return this.defensiveCopyOfArgs; + return this.args; } @Override @@ -128,7 +125,7 @@ public Signature getSignature() { if (this.signature == null) { this.signature = new MethodSignatureImpl(); } - return signature; + return this.signature; } @Override diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/SimpleAspectInstanceFactory.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/SimpleAspectInstanceFactory.java index 5d413bd697c7..ce243379e1c1 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/SimpleAspectInstanceFactory.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/SimpleAspectInstanceFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,6 +41,7 @@ public SimpleAspectInstanceFactory(Class> aspectClass) { this.aspectClass = aspectClass; } + /** * Return the specified aspect class (never {@code null}). */ @@ -48,7 +49,6 @@ public final Class> getAspectClass() { return this.aspectClass; } - @Override public final Object getAspectInstance() { try { diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/TypePatternClassFilter.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/TypePatternClassFilter.java index 9d2bc141c6f1..d075741490fd 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/TypePatternClassFilter.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/TypePatternClassFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ * Spring AOP {@link ClassFilter} implementation using AspectJ type matching. * * @author Rod Johnson + * @author Juergen Hoeller * @since 2.0 */ public class TypePatternClassFilter implements ClassFilter { @@ -76,17 +77,21 @@ public TypePatternClassFilter(String typePattern) { * or is recognized as invalid */ public void setTypePattern(String typePattern) { - Assert.notNull(typePattern); + Assert.notNull(typePattern, "Type pattern must not be null"); this.typePattern = typePattern; this.aspectJTypePatternMatcher = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution(). parseTypePattern(replaceBooleanOperators(typePattern)); } + /** + * Return the AspectJ type pattern to match. + */ public String getTypePattern() { - return typePattern; + return this.typePattern; } + /** * Should the pointcut apply to the given interface or target class? * @param clazz candidate target class @@ -95,9 +100,7 @@ public String getTypePattern() { */ @Override public boolean matches(Class> clazz) { - if (this.aspectJTypePatternMatcher == null) { - throw new IllegalStateException("No 'typePattern' has been set via ctor/setter."); - } + Assert.state(this.aspectJTypePatternMatcher != null, "No type pattern has been set"); return this.aspectJTypePatternMatcher.matches(clazz); } @@ -108,9 +111,8 @@ public boolean matches(Class> clazz) { *
This method converts back to {@code &&} for the AspectJ pointcut parser.
*/
private String replaceBooleanOperators(String pcExpr) {
- pcExpr = StringUtils.replace(pcExpr," and "," && ");
- pcExpr = StringUtils.replace(pcExpr, " or ", " || ");
- pcExpr = StringUtils.replace(pcExpr, " not ", " ! ");
- return pcExpr;
+ String result = StringUtils.replace(pcExpr," and "," && ");
+ result = StringUtils.replace(result, " or ", " || ");
+ return StringUtils.replace(result, " not ", " ! ");
}
}
diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java
index 98c74f7ad044..84ed46387389 100644
--- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java
+++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,7 +38,6 @@
import org.aspectj.lang.reflect.AjTypeSystem;
import org.aspectj.lang.reflect.PerClauseKind;
-import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotationUtils;
@@ -60,6 +59,9 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
private static final String AJC_MAGIC = "ajc$";
+ private static final Class>[] ASPECTJ_ANNOTATION_CLASSES = new Class>[] {
+ Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
+
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
@@ -121,59 +123,14 @@ public void validate(Class> aspectClass) throws AopConfigException {
}
}
- /**
- * The pointcut and advice annotations both have an "argNames" member which contains a
- * comma-separated list of the argument names. We use this (if non-empty) to build the
- * formal parameters for the pointcut.
- */
- protected AspectJExpressionPointcut createPointcutExpression(
- Method annotatedMethod, Class> declarationScope, String[] pointcutParameterNames) {
-
- Class> [] pointcutParameterTypes = new Class>[0];
- if (pointcutParameterNames != null) {
- pointcutParameterTypes = extractPointcutParameterTypes(pointcutParameterNames,annotatedMethod);
- }
-
- AspectJExpressionPointcut ajexp =
- new AspectJExpressionPointcut(declarationScope,pointcutParameterNames,pointcutParameterTypes);
- ajexp.setLocation(annotatedMethod.toString());
- return ajexp;
- }
-
- /**
- * Create the pointcut parameters needed by aspectj based on the given argument names
- * and the argument types that are available from the adviceMethod. Needs to take into
- * account (ignore) any JoinPoint based arguments as these are not pointcut context but
- * rather part of the advice execution context (thisJoinPoint, thisJoinPointStaticPart)
- */
- private Class>[] extractPointcutParameterTypes(String[] argNames, Method adviceMethod) {
- Class>[] ret = new Class>[argNames.length];
- Class>[] paramTypes = adviceMethod.getParameterTypes();
- if (argNames.length > paramTypes.length) {
- throw new IllegalStateException("Expecting at least " + argNames.length +
- " arguments in the advice declaration, but only found " + paramTypes.length);
- }
-
- // Make the simplifying assumption for now that all of the JoinPoint based arguments
- // come first in the advice declaration.
- int typeOffset = paramTypes.length - argNames.length;
- for (int i = 0; i < ret.length; i++) {
- ret[i] = paramTypes[i + typeOffset];
- }
- return ret;
- }
-
-
/**
* Find and return the first AspectJ annotation on the given method
- * (there should only be one anyway...)
+ * (there should only be one anyway...).
*/
@SuppressWarnings("unchecked")
protected static AspectJAnnotation> findAspectJAnnotationOnMethod(Method method) {
- Class>[] classesToLookFor = new Class>[] {
- Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
- for (Class> c : classesToLookFor) {
- AspectJAnnotation> foundAnnotation = findAnnotation(method, (Class Uses AspectJ 5 AJType reflection API, so is only supported on Java 5.
- * Enables us to work with different AspectJ instantiation models such as
- * "singleton", "pertarget" and "perthis".
+ * Uses AspectJ 5 AJType reflection API, enabling us to work with different
+ * AspectJ instantiation models such as "singleton", "pertarget" and "perthis".
*
* @author Rod Johnson
* @author Juergen Hoeller
@@ -102,20 +101,22 @@ public AspectMetadata(Class> aspectClass, String aspectName) {
this.ajType = ajType;
switch (this.ajType.getPerClause().getKind()) {
- case SINGLETON :
+ case SINGLETON:
this.perClausePointcut = Pointcut.TRUE;
return;
- case PERTARGET : case PERTHIS :
+ case PERTARGET:
+ case PERTHIS:
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
- ajexp.setLocation("@Aspect annotation on " + aspectClass.getName());
+ ajexp.setLocation(aspectClass.getName());
ajexp.setExpression(findPerClause(aspectClass));
+ ajexp.setPointcutDeclarationScope(aspectClass);
this.perClausePointcut = ajexp;
return;
- case PERTYPEWITHIN :
+ case PERTYPEWITHIN:
// Works with a type pattern
this.perClausePointcut = new ComposablePointcut(new TypePatternClassFilter(findPerClause(aspectClass)));
return;
- default :
+ default:
throw new AopConfigException(
"PerClause " + ajType.getPerClause().getKind() + " not supported by Spring AOP for " + aspectClass);
}
@@ -125,10 +126,8 @@ public AspectMetadata(Class> aspectClass, String aspectName) {
* Extract contents from String of form {@code pertarget(contents)}.
*/
private String findPerClause(Class> aspectClass) {
- // TODO when AspectJ provides this, we can remove this hack. Hence we don't
- // bother to make it elegant. Or efficient. Or robust :-)
String str = aspectClass.getAnnotation(Aspect.class).value();
- str = str.substring(str.indexOf("(") + 1);
+ str = str.substring(str.indexOf('(') + 1);
str = str.substring(0, str.length() - 1);
return str;
}
@@ -149,7 +148,7 @@ public Class> getAspectClass() {
}
/**
- * Return the aspect class.
+ * Return the aspect name.
*/
public String getAspectName() {
return this.aspectName;
diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectInstanceFactory.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectInstanceFactory.java
index f68fea5627ea..afb8ceb33291 100644
--- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectInstanceFactory.java
+++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectInstanceFactory.java
@@ -97,8 +97,19 @@ public AspectMetadata getAspectMetadata() {
@Override
public Object getAspectCreationMutex() {
- return (this.beanFactory instanceof ConfigurableBeanFactory ?
- ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex() : this);
+ if (this.beanFactory != null) {
+ if (this.beanFactory.isSingleton(name)) {
+ // Rely on singleton semantics provided by the factory -> no local lock.
+ return null;
+ }
+ else if (this.beanFactory instanceof ConfigurableBeanFactory) {
+ // No singleton guarantees from the factory -> let's lock locally but
+ // reuse the factory's singleton lock, just in case a lazy dependency
+ // of our advice bean happens to trigger the singleton lock implicitly...
+ return ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex();
+ }
+ }
+ return this;
}
/**
diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectJAdvisorsBuilder.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectJAdvisorsBuilder.java
index 5c9a7e7448b3..310ebca4599b 100644
--- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectJAdvisorsBuilder.java
+++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectJAdvisorsBuilder.java
@@ -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.
@@ -17,10 +17,10 @@
package org.springframework.aop.aspectj.annotation;
import java.util.Collections;
-import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import org.aspectj.lang.reflect.PerClauseKind;
@@ -43,12 +43,12 @@ public class BeanFactoryAspectJAdvisorsBuilder {
private final AspectJAdvisorFactory advisorFactory;
- private List Resulting Advisors will need to be evaluated for targets.
* @param introductionField the field to introspect
- * @return {@code null} if not an Advisor
+ * @return the Advisor instance, or {@code null} if not an Advisor
*/
private Advisor getDeclareParentsAdvisor(Field introductionField) {
DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
@@ -161,9 +186,7 @@ private Advisor getDeclareParentsAdvisor(Field introductionField) {
}
if (DeclareParents.class == declareParents.defaultImpl()) {
- // This is what comes back if it wasn't set. This seems bizarre...
- // TODO this restriction possibly should be relaxed
- throw new IllegalStateException("defaultImpl must be set on DeclareParents");
+ throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
}
return new DeclareParentsAdvisor(
@@ -197,6 +220,7 @@ private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Clas
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
+ ajexp.setBeanFactory(this.beanFactory);
return ajexp;
}
@@ -229,6 +253,15 @@ public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
+ case AtPointcut:
+ if (logger.isDebugEnabled()) {
+ logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
+ }
+ return null;
+ case AtAround:
+ springAdvice = new AspectJAroundAdvice(
+ candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
+ break;
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
@@ -253,15 +286,6 @@ public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
- case AtAround:
- springAdvice = new AspectJAroundAdvice(
- candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
- break;
- case AtPointcut:
- if (logger.isDebugEnabled()) {
- logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
- }
- return null;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
@@ -275,6 +299,7 @@ public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
+
return springAdvice;
}
diff --git a/spring-aop/src/main/java/org/springframework/aop/config/AbstractInterceptorDrivenBeanDefinitionDecorator.java b/spring-aop/src/main/java/org/springframework/aop/config/AbstractInterceptorDrivenBeanDefinitionDecorator.java
index 65169d1a8d04..6495f25af93b 100644
--- a/spring-aop/src/main/java/org/springframework/aop/config/AbstractInterceptorDrivenBeanDefinitionDecorator.java
+++ b/spring-aop/src/main/java/org/springframework/aop/config/AbstractInterceptorDrivenBeanDefinitionDecorator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -71,7 +71,7 @@ public final BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder defin
BeanDefinition interceptorDefinition = createInterceptorDefinition(node);
// generate name and register the interceptor
- String interceptorName = existingBeanName + "." + getInterceptorNameSuffix(interceptorDefinition);
+ String interceptorName = existingBeanName + '.' + getInterceptorNameSuffix(interceptorDefinition);
BeanDefinitionReaderUtils.registerBeanDefinition(
new BeanDefinitionHolder(interceptorDefinition, interceptorName), registry);
diff --git a/spring-aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java b/spring-aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java
index c2271500600d..72b5c6265393 100644
--- a/spring-aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java
+++ b/spring-aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,11 +31,10 @@
/**
* Utility class for handling registration of AOP auto-proxy creators.
*
- * Only a single auto-proxy creator can be registered yet multiple concrete
- * implementations are available. Therefore this class wraps a simple escalation
- * protocol, allowing classes to request a particular auto-proxy creator and know
- * that class, {@code or a subclass thereof}, will eventually be resident
- * in the application context.
+ * Only a single auto-proxy creator should be registered yet multiple concrete
+ * implementations are available. This class provides a simple escalation protocol,
+ * allowing a caller to request a particular auto-proxy creator and know that creator,
+ * or a more capable variant thereof, will be registered as a post-processor.
*
* @author Rob Harrop
* @author Juergen Hoeller
@@ -54,12 +53,10 @@ public abstract class AopConfigUtils {
/**
* Stores the auto proxy creator classes in escalation order.
*/
- private static final List Only a single auto-proxy creator can be registered and multiple tags may wish
- * to register different concrete implementations. As such this class delegates to
- * {@link AopConfigUtils} which wraps a simple escalation protocol. Therefore classes
- * may request a particular auto-proxy creator and know that class, or a subclass
- * thereof, will eventually be resident in the application context.
+ * Only a single auto-proxy creator should be registered and multiple configuration
+ * elements may wish to register different concrete implementations. As such this class
+ * delegates to {@link AopConfigUtils} which provides a simple escalation protocol.
+ * Callers may request a particular auto-proxy creator and know that creator,
+ * or a more capable variant thereof, will be registered as a post-processor.
*
* @author Rob Harrop
* @author Juergen Hoeller
@@ -81,11 +81,11 @@ public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
if (sourceElement != null) {
- boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
+ boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
- boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
+ boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
@@ -94,9 +94,8 @@ private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry,
private static void registerComponentIfNecessary(BeanDefinition beanDefinition, ParserContext parserContext) {
if (beanDefinition != null) {
- BeanComponentDefinition componentDefinition =
- new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
- parserContext.registerComponent(componentDefinition);
+ parserContext.registerComponent(
+ new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
}
}
diff --git a/spring-aop/src/main/java/org/springframework/aop/config/SimpleBeanFactoryAwareAspectInstanceFactory.java b/spring-aop/src/main/java/org/springframework/aop/config/SimpleBeanFactoryAwareAspectInstanceFactory.java
index 64cc673bab7b..22881292f60a 100644
--- a/spring-aop/src/main/java/org/springframework/aop/config/SimpleBeanFactoryAwareAspectInstanceFactory.java
+++ b/spring-aop/src/main/java/org/springframework/aop/config/SimpleBeanFactoryAwareAspectInstanceFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,8 +21,8 @@
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.Ordered;
+import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
-import org.springframework.util.StringUtils;
/**
* Implementation of {@link AspectInstanceFactory} that locates the aspect from the
@@ -50,9 +50,7 @@ public void setAspectBeanName(String aspectBeanName) {
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
- if (!StringUtils.hasText(this.aspectBeanName)) {
- throw new IllegalArgumentException("'aspectBeanName' is required");
- }
+ Assert.notNull(this.aspectBeanName, "'aspectBeanName' is required");
}
diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/AbstractAdvisingBeanPostProcessor.java b/spring-aop/src/main/java/org/springframework/aop/framework/AbstractAdvisingBeanPostProcessor.java
index 7f366d560296..47181986bf00 100644
--- a/spring-aop/src/main/java/org/springframework/aop/framework/AbstractAdvisingBeanPostProcessor.java
+++ b/spring-aop/src/main/java/org/springframework/aop/framework/AbstractAdvisingBeanPostProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -90,7 +90,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) {
return proxyFactory.getProxy(getProxyClassLoader());
}
- // No async proxy needed.
+ // No proxy needed.
return bean;
}
@@ -155,7 +155,7 @@ protected ProxyFactory prepareProxyFactory(Object bean, String beanName) {
* Subclasses may choose to implement this: for example,
* to change the interfaces exposed.
* The default implementation is empty.
- * @param proxyFactory ProxyFactory that is already configured with
+ * @param proxyFactory the ProxyFactory that is already configured with
* target, advisor and interfaces and will be used to create the proxy
* immediately after this method returns
* @since 4.2.3
diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java b/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java
index 40940374d8df..6a5a3cf70049 100644
--- a/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java
+++ b/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -93,7 +92,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
* List of Advisors. If an Advice is added, it will be wrapped
* in an Advisor before being added to this List.
*/
- private List
- * Mainly for use within the framework and in particular the binding facility
+ *
+ * Mainly for use within the framework and in particular the binding facility.
*
* @author Alef Arendsen
* @author Arjen Poutsma
@@ -43,14 +43,12 @@
*/
public abstract class PropertyMatches {
- //---------------------------------------------------------------------
- // Static section
- //---------------------------------------------------------------------
-
/** Default maximum property distance: 2 */
public static final int DEFAULT_MAX_DISTANCE = 2;
+ // Static factory methods
+
/**
* Create PropertyMatches for the given bean property.
* @param propertyName the name of the property to find possible matches for
@@ -90,9 +88,7 @@ public static PropertyMatches forField(String propertyName, Class> beanClass,
}
- //---------------------------------------------------------------------
- // Instance section
- //---------------------------------------------------------------------
+ // Instance state
private final String propertyName;
@@ -107,18 +103,19 @@ private PropertyMatches(String propertyName, String[] possibleMatches) {
this.possibleMatches = possibleMatches;
}
+
/**
* Return the name of the requested property.
*/
public String getPropertyName() {
- return propertyName;
+ return this.propertyName;
}
/**
* Return the calculated possible matches.
*/
public String[] getPossibleMatches() {
- return possibleMatches;
+ return this.possibleMatches;
}
/**
@@ -127,6 +124,9 @@ public String[] getPossibleMatches() {
*/
public abstract String buildErrorMessage();
+
+ // Implementation support for subclasses
+
protected void appendHintMessage(StringBuilder msg) {
msg.append("Did you mean ");
for (int i = 0; i < this.possibleMatches.length; i++) {
@@ -150,14 +150,14 @@ else if (i == this.possibleMatches.length - 2) {
* @return the distance value
*/
private static int calculateStringDistance(String s1, String s2) {
- if (s1.length() == 0) {
+ if (s1.isEmpty()) {
return s2.length();
}
- if (s2.length() == 0) {
+ if (s2.isEmpty()) {
return s1.length();
}
- int d[][] = new int[s1.length() + 1][s2.length() + 1];
+ int[][] d = new int[s1.length() + 1][s2.length() + 1];
for (int i = 0; i <= s1.length(); i++) {
d[i][0] = i;
}
@@ -166,45 +166,46 @@ private static int calculateStringDistance(String s1, String s2) {
}
for (int i = 1; i <= s1.length(); i++) {
- char s_i = s1.charAt(i - 1);
+ char c1 = s1.charAt(i - 1);
for (int j = 1; j <= s2.length(); j++) {
int cost;
- char t_j = s2.charAt(j - 1);
- if (s_i == t_j) {
+ char c2 = s2.charAt(j - 1);
+ if (c1 == c2) {
cost = 0;
}
else {
cost = 1;
}
- d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1),
- d[i - 1][j - 1] + cost);
+ d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1), d[i - 1][j - 1] + cost);
}
}
return d[s1.length()][s2.length()];
}
+
+ // Concrete subclasses
+
private static class BeanPropertyMatches extends PropertyMatches {
- private BeanPropertyMatches(String propertyName, Class> beanClass, int maxDistance) {
- super(propertyName, calculateMatches(propertyName,
- BeanUtils.getPropertyDescriptors(beanClass), maxDistance));
+ public BeanPropertyMatches(String propertyName, Class> beanClass, int maxDistance) {
+ super(propertyName,
+ calculateMatches(propertyName, BeanUtils.getPropertyDescriptors(beanClass), maxDistance));
}
/**
- * Generate possible property alternatives for the given property and
- * class. Internally uses the {@code getStringDistance} method, which
- * in turn uses the Levenshtein algorithm to determine the distance between
- * two Strings.
- * @param propertyDescriptors the JavaBeans property descriptors to search
+ * Generate possible property alternatives for the given property and class.
+ * Internally uses the {@code getStringDistance} method, which in turn uses
+ * the Levenshtein algorithm to determine the distance between two Strings.
+ * @param descriptors the JavaBeans property descriptors to search
* @param maxDistance the maximum distance to accept
*/
- private static String[] calculateMatches(String propertyName, PropertyDescriptor[] propertyDescriptors, int maxDistance) {
+ private static String[] calculateMatches(String name, PropertyDescriptor[] descriptors, int maxDistance) {
List Note that merely implementing {@link Aware} provides no default
- * functionality. Rather, processing must be done explicitly, for example
- * in a {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessor}.
+ * Note that merely implementing {@link Aware} provides no default functionality.
+ * Rather, processing must be done explicitly, for example in a
+ * {@link org.springframework.beans.factory.config.BeanPostProcessor}.
* Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
- * and {@link org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory}
- * for examples of processing {@code *Aware} interface callbacks.
+ * for an example of processing specific {@code *Aware} interface callbacks.
*
* @author Chris Beams
+ * @author Juergen Hoeller
* @since 3.1
*/
public interface Aware {
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/BeanDefinitionStoreException.java b/spring-beans/src/main/java/org/springframework/beans/factory/BeanDefinitionStoreException.java
index 47a2ec8c14b8..1d0fc9a7f4b1 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/BeanDefinitionStoreException.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/BeanDefinitionStoreException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -75,7 +75,7 @@ public BeanDefinitionStoreException(String resourceDescription, String msg, Thro
/**
* Create a new BeanDefinitionStoreException.
* @param resourceDescription description of the resource that the bean definition came from
- * @param beanName the name of the bean requested
+ * @param beanName the name of the bean
* @param msg the detail message (appended to an introductory message that indicates
* the resource and the name of the bean)
*/
@@ -86,28 +86,28 @@ public BeanDefinitionStoreException(String resourceDescription, String beanName,
/**
* Create a new BeanDefinitionStoreException.
* @param resourceDescription description of the resource that the bean definition came from
- * @param beanName the name of the bean requested
+ * @param beanName the name of the bean
* @param msg the detail message (appended to an introductory message that indicates
* the resource and the name of the bean)
* @param cause the root cause (may be {@code null})
*/
public BeanDefinitionStoreException(String resourceDescription, String beanName, String msg, Throwable cause) {
- super("Invalid bean definition with name '" + beanName + "' defined in " + resourceDescription + ": " + msg, cause);
+ super("Invalid bean definition with name '" + beanName + "' defined in " + resourceDescription + ": " + msg,
+ cause);
this.resourceDescription = resourceDescription;
this.beanName = beanName;
}
/**
- * Return the description of the resource that the bean
- * definition came from, if any.
+ * Return the description of the resource that the bean definition came from, if available.
*/
public String getResourceDescription() {
return this.resourceDescription;
}
/**
- * Return the name of the bean requested, if any.
+ * Return the name of the bean, if available.
*/
public String getBeanName() {
return this.beanName;
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java
index 58b2fd97bb67..83498c333e3d 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -63,28 +63,35 @@
* are supposed to override beans of the same name in any parent factory.
*
* Bean factory implementations should support the standard bean lifecycle interfaces
- * as far as possible. The full set of initialization methods and their standard order is: On shutdown of a bean factory, the following lifecycle methods apply: On shutdown of a bean factory, the following lifecycle methods apply:
+ * 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}.
- * @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
- * @throws BeansException if the bean could not be created
- * @since 3.0
- * @see ListableBeanFactory
- */
- Allows for specifying explicit constructor arguments / factory method arguments,
@@ -184,6 +174,23 @@ public interface BeanFactory {
*/
Object getBean(String name, Object... args) throws BeansException;
+ /**
+ * Return the bean instance that uniquely matches the given object type, if any.
+ * 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
+ * @throws BeansException if the bean could not be created
+ * @since 3.0
+ * @see ListableBeanFactory
+ */
+ Allows for specifying explicit constructor arguments / factory method arguments,
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactoryUtils.java b/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactoryUtils.java
index 42b749e6fa2a..7a67710ea941 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactoryUtils.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactoryUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -147,14 +147,7 @@ public static String[] beanNamesForTypeIncludingAncestors(ListableBeanFactory lb
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
String[] parentResult = beanNamesForTypeIncludingAncestors(
(ListableBeanFactory) hbf.getParentBeanFactory(), type);
- List An alternative to implementing DisposableBean is specifying a custom
- * destroy-method, for example in an XML bean definition.
- * For a list of all bean lifecycle methods, see the BeanFactory javadocs.
+ * A Spring-managed bean may also implement Java's {@link AutoCloseable} interface
+ * for the same purpose. An alternative to implementing an interface is specifying a
+ * custom destroy method, for example in an XML bean definition. For a list of all
+ * bean lifecycle methods, see the {@link BeanFactory BeanFactory javadocs}.
*
* @author Juergen Hoeller
* @since 12.08.2003
- * @see org.springframework.beans.factory.support.RootBeanDefinition#getDestroyMethodName
- * @see org.springframework.context.ConfigurableApplicationContext#close
+ * @see InitializingBean
+ * @see org.springframework.beans.factory.support.RootBeanDefinition#getDestroyMethodName()
+ * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons()
+ * @see org.springframework.context.ConfigurableApplicationContext#close()
*/
public interface DisposableBean {
/**
- * Invoked by a BeanFactory on destruction of a singleton.
- * @throws Exception in case of shutdown errors.
- * Exceptions will get logged but not rethrown to allow
- * other beans to release their resources too.
+ * Invoked by the containing {@code BeanFactory} on destruction of a bean.
+ * @throws Exception in case of shutdown errors. Exceptions will get logged
+ * but not rethrown to allow other beans to release their resources as well.
*/
void destroy() throws Exception;
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/FactoryBean.java b/spring-beans/src/main/java/org/springframework/beans/factory/FactoryBean.java
index 84763c37f6c3..ab465931aba1 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/FactoryBean.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/FactoryBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,31 +17,34 @@
package org.springframework.beans.factory;
/**
- * Interface to be implemented by objects used within a {@link BeanFactory}
- * which are themselves factories. If a bean implements this interface,
- * it is used as a factory for an object to expose, not directly as a bean
- * instance that will be exposed itself.
+ * Interface to be implemented by objects used within a {@link BeanFactory} which
+ * are themselves factories for individual objects. If a bean implements this
+ * interface, it is used as a factory for an object to expose, not directly as a
+ * bean instance that will be exposed itself.
*
- * NB: A bean that implements this interface cannot be used as a
- * normal bean. A FactoryBean is defined in a bean style, but the
- * object exposed for bean references ({@link #getObject()} is always
- * the object that it creates.
+ * NB: A bean that implements this interface cannot be used as a normal bean.
+ * A FactoryBean is defined in a bean style, but the object exposed for bean
+ * references ({@link #getObject()}) is always the object that it creates.
*
- * FactoryBeans can support singletons and prototypes, and can
- * either create objects lazily on demand or eagerly on startup.
- * The {@link SmartFactoryBean} interface allows for exposing
- * more fine-grained behavioral metadata.
+ * FactoryBeans can support singletons and prototypes, and can either create
+ * objects lazily on demand or eagerly on startup. The {@link SmartFactoryBean}
+ * interface allows for exposing more fine-grained behavioral metadata.
*
- * This interface is heavily used within the framework itself, for
- * example for the AOP {@link org.springframework.aop.framework.ProxyFactoryBean}
- * or the {@link org.springframework.jndi.JndiObjectFactoryBean}.
- * It can be used for application components as well; however,
- * this is not common outside of infrastructure code.
+ * This interface is heavily used within the framework itself, for example for
+ * the AOP {@link org.springframework.aop.framework.ProxyFactoryBean} or the
+ * {@link org.springframework.jndi.JndiObjectFactoryBean}. It can be used for
+ * custom components as well; however, this is only common for infrastructure code.
*
- * NOTE: FactoryBean objects participate in the containing
- * BeanFactory's synchronization of bean creation. There is usually no
- * need for internal synchronization other than for purposes of lazy
- * initialization within the FactoryBean itself (or the like).
+ * {@code FactoryBean} is a programmatic contract. Implementations are not
+ * supposed to rely on annotation-driven injection or other reflective facilities.
+ * {@link #getObjectType()} {@link #getObject()} invocations may arrive early in
+ * the bootstrap process, even ahead of any post-processor setup. If you need access
+ * other beans, implement {@link BeanFactoryAware} and obtain them programmatically.
+ *
+ * Finally, FactoryBean objects participate in the containing BeanFactory's
+ * synchronization of bean creation. There is usually no need for internal
+ * synchronization other than for purposes of lazy initialization within the
+ * FactoryBean itself (or the like).
*
* @author Rod Johnson
* @author Juergen Hoeller
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/InitializingBean.java b/spring-beans/src/main/java/org/springframework/beans/factory/InitializingBean.java
index 365bf99bf1ab..b0ca094510e3 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/InitializingBean.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/InitializingBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,31 +17,29 @@
package org.springframework.beans.factory;
/**
- * Interface to be implemented by beans that need to react once all their
- * properties have been set by a BeanFactory: for example, to perform custom
- * initialization, or merely to check that all mandatory properties have been set.
+ * Interface to be implemented by beans that need to react once all their properties
+ * have been set by a {@link BeanFactory}: e.g. to perform custom initialization,
+ * or merely to check that all mandatory properties have been set.
*
- * An alternative to implementing InitializingBean is specifying a custom
- * init-method, for example in an XML bean definition.
- * For a list of all bean lifecycle methods, see the BeanFactory javadocs.
+ * An alternative to implementing {@code InitializingBean} is specifying a custom
+ * init method, for example in an XML bean definition. For a list of all bean
+ * lifecycle methods, see the {@link BeanFactory BeanFactory javadocs}.
*
* @author Rod Johnson
- * @see BeanNameAware
- * @see BeanFactoryAware
- * @see BeanFactory
- * @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName
- * @see org.springframework.context.ApplicationContextAware
+ * @author Juergen Hoeller
+ * @see DisposableBean
+ * @see org.springframework.beans.factory.config.BeanDefinition#getPropertyValues()
+ * @see org.springframework.beans.factory.support.AbstractBeanDefinition#getInitMethodName()
*/
public interface InitializingBean {
/**
- * Invoked by a BeanFactory after it has set all bean properties supplied
- * (and satisfied BeanFactoryAware and ApplicationContextAware).
- * This method allows the bean instance to perform initialization only
- * possible when all bean properties have been set and to throw an
- * exception in the event of misconfiguration.
- * @throws Exception in the event of misconfiguration (such
- * as failure to set an essential property) or if initialization fails.
+ * Invoked by the containing {@code BeanFactory} after it has set all bean properties
+ * and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.
+ * This method allows the bean instance to perform validation of its overall
+ * configuration and final initialization when all bean properties have been set.
+ * @throws Exception in the event of misconfiguration (such as failure to set an
+ * essential property) or if initialization fails for any other reason
*/
void afterPropertiesSet() throws Exception;
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/InjectionPoint.java b/spring-beans/src/main/java/org/springframework/beans/factory/InjectionPoint.java
index 0a3d55a9312a..38ace23fd40b 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/InjectionPoint.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/InjectionPoint.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -111,6 +111,17 @@ public Annotation[] getAnnotations() {
}
}
+ /**
+ * Retrieve a field/parameter annotation of the given type, if any.
+ * @param annotationType the annotation type to retrieve
+ * @return the annotation instance, or {@code null} if none found
+ * @since 4.3.9
+ */
+ public A getAnnotation(Class annotationType) {
+ return (this.field != null ? this.field.getAnnotation(annotationType) :
+ this.methodParameter.getParameterAnnotation(annotationType));
+ }
+
/**
* Return the type declared by the underlying field or method/constructor parameter,
* indicating the injection type.
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java
index e8be3322896c..1c0c70b46f10 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -243,7 +243,9 @@ Note that this method considers objects created by FactoryBeans, which means
+ * that FactoryBeans will get initialized in order to determine their object type.
* @param annotationType the type of annotation to look for
* @return the names of all matching beans
* @since 4.0
@@ -253,6 +255,8 @@ Note that this method considers objects created by FactoryBeans, which means
+ * that FactoryBeans will get initialized in order to determine their object type.
* @param annotationType the type of annotation to look for
* @return a Map with the matching beans, containing the bean names as
* keys and the corresponding bean instances as values
@@ -267,7 +271,7 @@ This interface can be introduced to avoid a brittle dependence
- * on bean name in objects used with Spring IoC and Spring AOP.
+ * 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 @@
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();
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/NoSuchBeanDefinitionException.java b/spring-beans/src/main/java/org/springframework/beans/factory/NoSuchBeanDefinitionException.java
index 106fa0cafc9c..c02210581b69 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/NoSuchBeanDefinitionException.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/NoSuchBeanDefinitionException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,8 @@
package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
+import org.springframework.core.ResolvableType;
+import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
@@ -26,6 +28,7 @@
*
* @author Rod Johnson
* @author Juergen Hoeller
+ * @author Stephane Nicoll
* @see BeanFactory#getBean(String)
* @see BeanFactory#getBean(Class)
* @see NoUniqueBeanDefinitionException
@@ -33,11 +36,9 @@
@SuppressWarnings("serial")
public class NoSuchBeanDefinitionException extends BeansException {
- /** Name of the missing bean */
private String beanName;
- /** Required type of the missing bean */
- private Class> beanType;
+ private ResolvableType resolvableType;
/**
@@ -45,7 +46,7 @@ public class NoSuchBeanDefinitionException extends BeansException {
* @param name the name of the missing bean
*/
public NoSuchBeanDefinitionException(String name) {
- super("No bean named '" + name + "' is defined");
+ super("No bean named '" + name + "' available");
this.beanName = name;
}
@@ -55,7 +56,7 @@ public NoSuchBeanDefinitionException(String name) {
* @param message detailed message describing the problem
*/
public NoSuchBeanDefinitionException(String name, String message) {
- super("No bean named '" + name + "' is defined: " + message);
+ super("No bean named '" + name + "' available: " + message);
this.beanName = name;
}
@@ -64,8 +65,7 @@ public NoSuchBeanDefinitionException(String name, String message) {
* @param type required type of the missing bean
*/
public NoSuchBeanDefinitionException(Class> type) {
- super("No qualifying bean of type [" + type.getName() + "] is defined");
- this.beanType = type;
+ this(ResolvableType.forClass(type));
}
/**
@@ -74,8 +74,28 @@ public NoSuchBeanDefinitionException(Class> type) {
* @param message detailed message describing the problem
*/
public NoSuchBeanDefinitionException(Class> type, String message) {
- super("No qualifying bean of type [" + type.getName() + "] is defined: " + message);
- this.beanType = type;
+ this(ResolvableType.forClass(type), message);
+ }
+
+ /**
+ * Create a new {@code NoSuchBeanDefinitionException}.
+ * @param type full type declaration of the missing bean
+ * @since 4.3.4
+ */
+ public NoSuchBeanDefinitionException(ResolvableType type) {
+ super("No qualifying bean of type '" + type + "' available");
+ this.resolvableType = type;
+ }
+
+ /**
+ * Create a new {@code NoSuchBeanDefinitionException}.
+ * @param type full type declaration of the missing bean
+ * @param message detailed message describing the problem
+ * @since 4.3.4
+ */
+ public NoSuchBeanDefinitionException(ResolvableType type, String message) {
+ super("No qualifying bean of type '" + type + "' available: " + message);
+ this.resolvableType = type;
}
/**
@@ -83,12 +103,15 @@ public NoSuchBeanDefinitionException(Class> type, String message) {
* @param type required type of the missing bean
* @param dependencyDescription a description of the originating dependency
* @param message detailed message describing the problem
+ * @deprecated as of 4.3.4, in favor of {@link #NoSuchBeanDefinitionException(ResolvableType, String)}
*/
+ @Deprecated
public NoSuchBeanDefinitionException(Class> type, String dependencyDescription, String message) {
- super("No qualifying bean of type [" + type.getName() + "] found for dependency" +
+ super("No qualifying bean" + (!StringUtils.hasLength(dependencyDescription) ?
+ " of type '" + ClassUtils.getQualifiedName(type) + "'" : "") + " found for dependency" +
(StringUtils.hasLength(dependencyDescription) ? " [" + dependencyDescription + "]" : "") +
": " + message);
- this.beanType = type;
+ this.resolvableType = ResolvableType.forClass(type);
}
@@ -100,10 +123,20 @@ public String getBeanName() {
}
/**
- * Return the required type of the missing bean, if it was a lookup by type that failed.
+ * Return the required type of the missing bean, if it was a lookup by type
+ * that failed.
*/
public Class> getBeanType() {
- return this.beanType;
+ return (this.resolvableType != null ? this.resolvableType.resolve() : null);
+ }
+
+ /**
+ * Return the required {@link ResolvableType} of the missing bean, if it was a lookup
+ * by type that failed.
+ * @since 4.3.4
+ */
+ public ResolvableType getResolvableType() {
+ return this.resolvableType;
}
/**
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/ObjectFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/ObjectFactory.java
index 40f807dd543d..9b923624855f 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/ObjectFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/ObjectFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@ public interface ObjectFactory Only one constructor (at max) of any given bean class may carry this
- * annotation, indicating the constructor to autowire when used as a Spring
- * bean. Such a constructor does not have to be public.
+ * Only one constructor (at max) of any given bean class may declare this annotation
+ * with the 'required' parameter set to {@code true}, indicating the constructor
+ * to autowire when used as a Spring bean. If multiple non-required constructors
+ * declare the annotation, they will be considered as candidates for autowiring.
+ * The constructor with the greatest number of dependencies that can be satisfied by
+ * matching beans in the Spring container will be chosen. If none of the candidates
+ * can be satisfied, then a standard default constructor (if present) will be used.
+ * If a class only declares a single constructor to begin with, it will always be used,
+ * even if not annotated. An annotated constructor does not have to be public.
*
- * Fields are injected right after construction of a bean, before any
- * config methods are invoked. Such a config field does not have to be public.
+ * Fields are injected right after construction of a bean, before any config methods
+ * are invoked. Such a config field does not have to be public.
*
- * Config methods may have an arbitrary name and any number of arguments;
- * each of those arguments will be autowired with a matching bean in the
- * Spring container. Bean property setter methods are effectively just
- * a special case of such a general config method. Such config methods
- * do not have to be public.
+ * Config methods may have an arbitrary name and any number of arguments; each of
+ * those arguments will be autowired with a matching bean in the Spring container.
+ * Bean property setter methods are effectively just a special case of such a general
+ * config method. Such config methods do not have to be public.
*
- * In the case of multiple argument methods, the 'required' parameter is
- * applicable for all arguments.
+ * In the case of a multi-arg constructor or method, the 'required' parameter is
+ * applicable to all arguments. Individual parameters may be declared as Java-8-style
+ * {@link java.util.Optional}, overriding the base required semantics.
*
- * In case of a {@link java.util.Collection} or {@link java.util.Map}
- * dependency type, the container will autowire all beans matching the
- * declared value type. In case of a Map, the keys must be declared as
- * type String and will be resolved to the corresponding bean names.
+ * In case of a {@link java.util.Collection} or {@link java.util.Map} dependency type,
+ * the container autowires all beans matching the declared value type. For such purposes,
+ * the map keys must be declared as type String which will be resolved to the corresponding
+ * bean names. Such a container-provided collection will be ordered, taking into account
+ * {@link org.springframework.core.Ordered}/{@link org.springframework.core.annotation.Order}
+ * values of the target components, otherwise following their registration order in the
+ * container. Alternatively, a single matching target bean may also be a generally typed
+ * {@code Collection} or {@code Map} itself, getting injected as such.
*
* Note that actual injection is performed through a
* {@link org.springframework.beans.factory.config.BeanPostProcessor
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java
index 258f66bf4d22..b0e8c609ccd7 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -74,15 +74,15 @@
* Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
* if available, as a direct alternative to Spring's own {@code @Autowired}.
*
- * Only one constructor (at max) of any given bean class may carry this
- * annotation with the 'required' parameter set to {@code true},
- * indicating the constructor to autowire when used as a Spring bean.
- * If multiple non-required constructors carry the annotation, they
- * will be considered as candidates for autowiring. The constructor with
- * the greatest number of dependencies that can be satisfied by matching
- * beans in the Spring container will be chosen. If none of the candidates
- * can be satisfied, then a default constructor (if present) will be used.
- * An annotated constructor does not have to be public.
+ * Only one constructor (at max) of any given bean class may declare this annotation
+ * with the 'required' parameter set to {@code true}, indicating the constructor
+ * to autowire when used as a Spring bean. If multiple non-required constructors
+ * declare the annotation, they will be considered as candidates for autowiring.
+ * The constructor with the greatest number of dependencies that can be satisfied by
+ * matching beans in the Spring container will be chosen. If none of the candidates
+ * can be satisfied, then a standard default constructor (if present) will be used.
+ * If a class only declares a single constructor to begin with, it will always be used,
+ * even if not annotated. An annotated constructor does not have to be public.
*
* Fields are injected right after construction of a bean, before any
* config methods are invoked. Such a config field does not have to be public.
@@ -120,7 +120,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
protected final Log logger = LogFactory.getLog(getClass());
private final Set The default autowired annotation type is the Spring-provided
- * {@link Autowired} annotation, as well as {@link Value}.
+ * The default autowired annotation type is the Spring-provided {@link Autowired}
+ * annotation, as well as {@link Value}.
* This setter property exists so that developers can provide their own
- * (non-Spring-specific) annotation type to indicate that a member is
- * supposed to be autowired.
+ * (non-Spring-specific) annotation type to indicate that a member is supposed
+ * to be autowired.
*/
public void setAutowiredAnnotationType(Class extends Annotation> autowiredAnnotationType) {
Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null");
@@ -178,11 +178,11 @@ public void setAutowiredAnnotationType(Class extends Annotation> autowiredAnno
/**
* Set the 'autowired' annotation types, to be used on constructors, fields,
* setter methods and arbitrary config methods.
- * The default autowired annotation type is the Spring-provided
- * {@link Autowired} annotation, as well as {@link Value}.
+ * The default autowired annotation type is the Spring-provided {@link Autowired}
+ * annotation, as well as {@link Value}.
* This setter property exists so that developers can provide their own
- * (non-Spring-specific) annotation types to indicate that a member is
- * supposed to be autowired.
+ * (non-Spring-specific) annotation types to indicate that a member is supposed
+ * to be autowired.
*/
public void setAutowiredAnnotationTypes(Set For example if using 'required=true' (the default),
- * this value should be {@code true}; but if using
- * 'optional=false', this value should be {@code false}.
+ * For example if using 'required=true' (the default), this value should be
+ * {@code true}; but if using 'optional=false', this value should be {@code false}.
* @see #setRequiredParameterName(String)
*/
public void setRequiredParameterValue(boolean requiredParameterValue) {
@@ -220,10 +218,10 @@ public int getOrder() {
}
@Override
- public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+ public void setBeanFactory(BeanFactory beanFactory) {
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException(
- "AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory");
+ "AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory: " + beanFactory);
}
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
@@ -238,35 +236,56 @@ public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, C
}
@Override
- public Constructor>[] determineCandidateConstructors(Class> beanClass, final String beanName) throws BeansException {
+ public Constructor>[] determineCandidateConstructors(Class> beanClass, final String beanName)
+ throws BeanCreationException {
+
+ // Let's check for lookup methods here..
if (!this.lookupMethodsChecked.contains(beanName)) {
- ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
- @Override
- public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
- Lookup lookup = method.getAnnotation(Lookup.class);
- if (lookup != null) {
- LookupOverride override = new LookupOverride(method, lookup.value());
- try {
- RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
- mbd.getMethodOverrides().addOverride(override);
- }
- catch (NoSuchBeanDefinitionException ex) {
- throw new BeanCreationException(beanName,
- "Cannot apply @Lookup to beans without corresponding bean definition");
+ try {
+ ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
+ @Override
+ public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
+ Lookup lookup = method.getAnnotation(Lookup.class);
+ if (lookup != null) {
+ LookupOverride override = new LookupOverride(method, lookup.value());
+ try {
+ RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
+ mbd.getMethodOverrides().addOverride(override);
+ }
+ catch (NoSuchBeanDefinitionException ex) {
+ throw new BeanCreationException(beanName,
+ "Cannot apply @Lookup to beans without corresponding bean definition");
+ }
}
}
- }
- });
+ });
+ }
+ catch (IllegalStateException ex) {
+ throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
+ }
+ catch (NoClassDefFoundError err) {
+ throw new BeanCreationException(beanName, "Failed to introspect bean class [" + beanClass.getName() +
+ "] for lookup method metadata: could not find class that it depends on", err);
+ }
this.lookupMethodsChecked.add(beanName);
}
// Quick check on the concurrent map first, with minimal locking.
Constructor>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
+ // Fully synchronized resolution now...
synchronized (this.candidateConstructorsCache) {
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
- Constructor>[] rawCandidates = beanClass.getDeclaredConstructors();
+ Constructor>[] rawCandidates;
+ try {
+ rawCandidates = beanClass.getDeclaredConstructors();
+ }
+ catch (Throwable ex) {
+ throw new BeanCreationException(beanName,
+ "Resolution of declared constructors on bean Class [" + beanClass.getName() +
+ "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
+ }
List Please note that an 'init' method may still need to implemented (and may
- * still be desirable), because all that this class does is enforce that a
+ * Please note that an 'init' method may still need to be implemented (and may
+ * still be desirable), because all that this class does is enforcing that a
* 'required' property has actually been configured with a value. It does
* not check anything else... In particular, it does not check that a
* configured value is not {@code null}.
@@ -141,8 +141,7 @@ public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, C
@Override
public PropertyValues postProcessPropertyValues(
- PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
- throws BeansException {
+ PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
if (!this.validatedBeanNames.contains(beanName)) {
if (!shouldSkip(this.beanFactory, beanName)) {
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/AbstractFactoryBean.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/AbstractFactoryBean.java
index 85faab006b05..ab473c3121bc 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/config/AbstractFactoryBean.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/AbstractFactoryBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.FactoryBeanNotInitializedException;
import org.springframework.beans.factory.InitializingBean;
+import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
@@ -153,7 +154,7 @@ public final T getObject() throws Exception {
}
/**
- * Determine an 'eager singleton' instance, exposed in case of a
+ * Determine an 'early singleton' instance, exposed in case of a
* circular reference. Not called in a non-circular scenario.
*/
@SuppressWarnings("unchecked")
@@ -176,9 +177,7 @@ private T getEarlySingletonInstance() throws Exception {
* @throws IllegalStateException if the singleton instance is not initialized
*/
private T getSingletonInstance() throws IllegalStateException {
- if (!this.initialized) {
- throw new IllegalStateException("Singleton instance not initialized yet");
- }
+ Assert.state(this.initialized, "Singleton instance not initialized yet");
return this.singletonInstance;
}
@@ -218,7 +217,7 @@ public void destroy() throws Exception {
* FactoryBean is supposed to implement, for use with an 'early singleton
* proxy' that will be exposed in case of a circular reference.
* The default implementation returns this FactoryBean's object type,
- * provided that it is an interface, or {@code null} else. The latter
+ * provided that it is an interface, or {@code null} otherwise. The latter
* indicates that early singleton access is not supported by this FactoryBean.
* This will lead to a FactoryBeanNotInitializedException getting thrown.
* @return the interfaces to use for 'early singletons',
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java
index 43602b48ebf8..61b524077028 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java
@@ -21,6 +21,8 @@
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 @@ Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String be
*/
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.
+ * 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)
+ */
+ Note that this does not have to be the actual class name used at runtime, in
- * case of a child definition overriding/inheriting the class name from its parent.
- * Hence, do not consider this to be the definitive bean type at runtime but
- * rather only use it for parsing purposes at the individual bean definition level.
+ * Return the name of the parent definition of this bean definition, if any.
*/
- String getBeanClassName();
+ String getParentName();
/**
- * Override the bean class name of this bean definition.
+ * Specify the bean class name of this bean definition.
* The class name can be modified during bean factory post-processing,
* typically replacing the original class name with a parsed variant of it.
+ * @see #setParentName
+ * @see #setFactoryBeanName
+ * @see #setFactoryMethodName
*/
void setBeanClassName(String beanClassName);
/**
- * Return the factory bean name, if any.
- */
- String getFactoryBeanName();
-
- /**
- * Specify the factory bean to use, if any.
- */
- void setFactoryBeanName(String factoryBeanName);
-
- /**
- * Return a factory method, if any.
+ * Return the current bean class name of this bean definition.
+ * Note that this does not have to be the actual class name used at runtime, in
+ * case of a child definition overriding/inheriting the class name from its parent.
+ * Also, this may just be the class that a factory method is called on, or it may
+ * even be empty in case of a factory bean reference that a method is called on.
+ * Hence, do not consider this to be the definitive bean type at runtime but
+ * rather only use it for parsing purposes at the individual bean definition level.
+ * @see #getParentName()
+ * @see #getFactoryBeanName()
+ * @see #getFactoryMethodName()
*/
- String getFactoryMethodName();
+ String getBeanClassName();
/**
- * Specify a factory method, if any. This method will be invoked with
- * constructor arguments, or with no arguments if none are specified.
- * The method will be invoked on the specified factory bean, if any,
- * or otherwise as a static method on the local bean class.
- * @param factoryMethodName static factory method name,
- * or {@code null} if normal constructor creation should be used
- * @see #getBeanClassName()
+ * Override the target scope of this bean, specifying a new scope name.
+ * @see #SCOPE_SINGLETON
+ * @see #SCOPE_PROTOTYPE
*/
- void setFactoryMethodName(String factoryMethodName);
+ void setScope(String scope);
/**
* Return the name of the current target scope for this bean,
@@ -138,11 +129,11 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String getScope();
/**
- * Override the target scope of this bean, specifying a new scope name.
- * @see #SCOPE_SINGLETON
- * @see #SCOPE_PROTOTYPE
+ * Set whether this bean should be lazily initialized.
+ * If {@code false}, the bean will get instantiated on startup by bean
+ * factories that perform eager initialization of singletons.
*/
- void setScope(String scope);
+ void setLazyInit(boolean lazyInit);
/**
* Return whether this bean should be lazily initialized, i.e. not
@@ -151,11 +142,10 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
boolean isLazyInit();
/**
- * Set whether this bean should be lazily initialized.
- * If {@code false}, the bean will get instantiated on startup by bean
- * factories that perform eager initialization of singletons.
+ * Set the names of the beans that this bean depends on being initialized.
+ * The bean factory will guarantee that these beans get initialized first.
*/
- void setLazyInit(boolean lazyInit);
+ void setDependsOn(String... dependsOn);
/**
* Return the bean names that this bean depends on.
@@ -163,10 +153,13 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String[] getDependsOn();
/**
- * Set the names of the beans that this bean depends on being initialized.
- * The bean factory will guarantee that these beans get initialized first.
+ * Set whether this bean is a candidate for getting autowired into some other bean.
+ * Note that this flag is designed to only affect type-based autowiring.
+ * It does not affect explicit references by name, which will get resolved even
+ * if the specified bean is not marked as an autowire candidate. As a consequence,
+ * autowiring by name will nevertheless inject a bean if the name matches.
*/
- void setDependsOn(String... dependsOn);
+ void setAutowireCandidate(boolean autowireCandidate);
/**
* Return whether this bean is a candidate for getting autowired into some other bean.
@@ -174,24 +167,43 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
boolean isAutowireCandidate();
/**
- * Set whether this bean is a candidate for getting autowired into some other bean.
+ * Set whether this bean is a primary autowire candidate.
+ * If this value is {@code true} for exactly one bean among multiple
+ * matching candidates, it will serve as a tie-breaker.
*/
- void setAutowireCandidate(boolean autowireCandidate);
+ void setPrimary(boolean primary);
/**
* Return whether this bean is a primary autowire candidate.
- * If this value is true for exactly one bean among multiple
- * matching candidates, it will serve as a tie-breaker.
*/
boolean isPrimary();
/**
- * Set whether this bean is a primary autowire candidate.
- * If this value is true for exactly one bean among multiple
- * matching candidates, it will serve as a tie-breaker.
+ * Specify the factory bean to use, if any.
+ * This the name of the bean to call the specified factory method on.
+ * @see #setFactoryMethodName
*/
- void setPrimary(boolean primary);
+ void setFactoryBeanName(String factoryBeanName);
+
+ /**
+ * Return the factory bean name, if any.
+ */
+ String getFactoryBeanName();
+
+ /**
+ * Specify a factory method, if any. This method will be invoked with
+ * constructor arguments, or with no arguments if none are specified.
+ * The method will be invoked on the specified factory bean, if any,
+ * or otherwise as a static method on the local bean class.
+ * @see #setFactoryBeanName
+ * @see #setBeanClassName
+ */
+ void setFactoryMethodName(String factoryMethodName);
+ /**
+ * Return a factory method, if any.
+ */
+ String getFactoryMethodName();
/**
* Return the constructor argument values for this bean.
@@ -208,6 +220,8 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
MutablePropertyValues getPropertyValues();
+ // Read-only attributes
+
/**
* Return whether this a Singleton, with a single, shared instance
* returned on all calls.
@@ -218,6 +232,7 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
/**
* Return whether this a Prototype, with an independent instance
* returned for each call.
+ * @since 3.0
* @see #SCOPE_PROTOTYPE
*/
boolean isPrototype();
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/CustomScopeConfigurer.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/CustomScopeConfigurer.java
index dc1516ab026b..a110bc4461bb 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/config/CustomScopeConfigurer.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/CustomScopeConfigurer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -102,12 +102,12 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
}
else if (value instanceof Class) {
Class> scopeClass = (Class>) value;
- Assert.isAssignable(Scope.class, scopeClass);
+ Assert.isAssignable(Scope.class, scopeClass, "Invalid scope class");
beanFactory.registerScope(scopeKey, (Scope) BeanUtils.instantiateClass(scopeClass));
}
else if (value instanceof String) {
Class> scopeClass = ClassUtils.resolveClassName((String) value, this.beanClassLoader);
- Assert.isAssignable(Scope.class, scopeClass);
+ Assert.isAssignable(Scope.class, scopeClass, "Invalid scope class");
beanFactory.registerScope(scopeKey, (Scope) BeanUtils.instantiateClass(scopeClass));
}
else {
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/DependencyDescriptor.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/DependencyDescriptor.java
index 82c6883cc189..bda5e0c0b7dc 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/config/DependencyDescriptor.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/DependencyDescriptor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.InjectionPoint;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
-import org.springframework.core.GenericCollectionTypeResolver;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
@@ -63,6 +62,8 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
private Class> containingClass;
+ private volatile ResolvableType resolvableType;
+
/**
* Create a new descriptor for a method or constructor parameter.
@@ -214,6 +215,7 @@ public Object resolveCandidate(String beanName, Class> requiredType, BeanFacto
*/
public void increaseNestingLevel() {
this.nestingLevel++;
+ this.resolvableType = null;
if (this.methodParameter != null) {
this.methodParameter.increaseNestingLevel();
}
@@ -227,6 +229,7 @@ public void increaseNestingLevel() {
*/
public void setContainingClass(Class> containingClass) {
this.containingClass = containingClass;
+ this.resolvableType = null;
if (this.methodParameter != null) {
GenericTypeResolver.resolveParameterType(this.methodParameter, containingClass);
}
@@ -237,14 +240,20 @@ public void setContainingClass(Class> containingClass) {
* @since 4.0
*/
public ResolvableType getResolvableType() {
- return (this.field != null ? ResolvableType.forField(this.field, this.nestingLevel, this.containingClass) :
- ResolvableType.forMethodParameter(this.methodParameter));
+ ResolvableType resolvableType = this.resolvableType;
+ if (resolvableType == null) {
+ resolvableType = (this.field != null ?
+ ResolvableType.forField(this.field, this.nestingLevel, this.containingClass) :
+ ResolvableType.forMethodParameter(this.methodParameter));
+ this.resolvableType = resolvableType;
+ }
+ return resolvableType;
}
/**
* Return whether a fallback match is allowed.
* This is {@code false} by default but may be overridden to return {@code true} in order
- * to suggest to a {@link org.springframework.beans.factory.support.AutowireCandidateResolver}
+ * to suggest to an {@link org.springframework.beans.factory.support.AutowireCandidateResolver}
* that a fallback match is acceptable as well.
* @since 4.0
*/
@@ -299,7 +308,6 @@ public Class> getDependencyType() {
Type[] args = ((ParameterizedType) type).getActualTypeArguments();
type = args[args.length - 1];
}
- // TODO: Object.class if unresolvable
}
if (type instanceof Class) {
return (Class>) type;
@@ -324,31 +332,37 @@ else if (type instanceof ParameterizedType) {
/**
* Determine the generic element type of the wrapped Collection parameter/field, if any.
* @return the generic type, or {@code null} if none
+ * @deprecated as of 4.3.6, in favor of direct {@link ResolvableType} usage
*/
+ @Deprecated
public Class> getCollectionType() {
return (this.field != null ?
- GenericCollectionTypeResolver.getCollectionFieldType(this.field, this.nestingLevel) :
- GenericCollectionTypeResolver.getCollectionParameterType(this.methodParameter));
+ org.springframework.core.GenericCollectionTypeResolver.getCollectionFieldType(this.field, this.nestingLevel) :
+ org.springframework.core.GenericCollectionTypeResolver.getCollectionParameterType(this.methodParameter));
}
/**
* Determine the generic key type of the wrapped Map parameter/field, if any.
* @return the generic type, or {@code null} if none
+ * @deprecated as of 4.3.6, in favor of direct {@link ResolvableType} usage
*/
+ @Deprecated
public Class> getMapKeyType() {
return (this.field != null ?
- GenericCollectionTypeResolver.getMapKeyFieldType(this.field, this.nestingLevel) :
- GenericCollectionTypeResolver.getMapKeyParameterType(this.methodParameter));
+ org.springframework.core.GenericCollectionTypeResolver.getMapKeyFieldType(this.field, this.nestingLevel) :
+ org.springframework.core.GenericCollectionTypeResolver.getMapKeyParameterType(this.methodParameter));
}
/**
* Determine the generic value type of the wrapped Map parameter/field, if any.
* @return the generic type, or {@code null} if none
+ * @deprecated as of 4.3.6, in favor of direct {@link ResolvableType} usage
*/
+ @Deprecated
public Class> getMapValueType() {
return (this.field != null ?
- GenericCollectionTypeResolver.getMapValueFieldType(this.field, this.nestingLevel) :
- GenericCollectionTypeResolver.getMapValueParameterType(this.methodParameter));
+ org.springframework.core.GenericCollectionTypeResolver.getMapValueFieldType(this.field, this.nestingLevel) :
+ org.springframework.core.GenericCollectionTypeResolver.getMapValueParameterType(this.methodParameter));
}
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/DestructionAwareBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/DestructionAwareBeanPostProcessor.java
index 92316f13b297..e2e8c4617254 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/config/DestructionAwareBeanPostProcessor.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/DestructionAwareBeanPostProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,16 +30,16 @@
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
/**
- * Apply this BeanPostProcessor to the given bean instance before
- * its destruction. Can invoke custom destruction callbacks.
- * Like DisposableBean's {@code destroy} and a custom destroy method,
- * this callback just applies to singleton beans in the factory (including
- * inner beans).
+ * Apply this BeanPostProcessor to the given bean instance before its
+ * destruction, e.g. invoking custom destruction callbacks.
+ * Like DisposableBean's {@code destroy} and a custom destroy method, this
+ * callback will only apply to beans which the container fully manages the
+ * lifecycle for. This is usually the case for singletons and scoped beans.
* @param bean the bean instance to be destroyed
* @param beanName the name of the bean
* @throws org.springframework.beans.BeansException in case of errors
- * @see org.springframework.beans.factory.DisposableBean
- * @see org.springframework.beans.factory.support.AbstractBeanDefinition#setDestroyMethodName
+ * @see org.springframework.beans.factory.DisposableBean#destroy()
+ * @see org.springframework.beans.factory.support.AbstractBeanDefinition#setDestroyMethodName(String)
*/
void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessor.java
index 964ee204b276..62c0dbdfaa53 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessor.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -71,9 +71,8 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
/**
* Perform operations after the bean has been instantiated, via a constructor or factory method,
* but before Spring property population (from explicit properties or autowiring) occurs.
- * This is the ideal callback for performing field injection on the given bean instance.
- * See Spring's own {@link org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor}
- * for a typical example.
+ * This is the ideal callback for performing custom field injection on the given bean
+ * instance, right before Spring's autowiring kicks in.
* @param bean the bean instance created, with properties not having been set yet
* @param beanName the name of the bean
* @return {@code true} if properties should be set on the bean; {@code false}
@@ -103,7 +102,6 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
* @see org.springframework.beans.MutablePropertyValues
*/
PropertyValues postProcessPropertyValues(
- PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
- throws BeansException;
+ PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
}
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessorAdapter.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessorAdapter.java
index 3e02846fcb5b..3f7e1746b70d 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessorAdapter.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessorAdapter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -66,8 +66,7 @@ public boolean postProcessAfterInstantiation(Object bean, String beanName) throw
@Override
public PropertyValues postProcessPropertyValues(
- PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
- throws BeansException {
+ PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/ListFactoryBean.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/ListFactoryBean.java
index fb251c4243b3..3ab96831092d 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/config/ListFactoryBean.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/ListFactoryBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
import org.springframework.beans.BeanUtils;
import org.springframework.beans.TypeConverter;
-import org.springframework.core.GenericCollectionTypeResolver;
+import org.springframework.core.ResolvableType;
/**
* Simple factory for shared List instances. Allows for central setup
@@ -86,7 +86,7 @@ protected List YAML is a nice human-readable format for configuration, and it has some
+ * useful hierarchical properties. It's more or less a superset of JSON, so it
+ * has a lot of similar features.
+ *
+ * If multiple resources are provided the later ones will override entries in
+ * the earlier ones hierarchically; that is, all entries with the same nested key
+ * of type {@code Map} at any depth are merged. For example:
*
* YAML is a nice human-readable format for configuration, and it has some
+ * useful hierarchical properties. It's more or less a superset of JSON, so it
+ * has a lot of similar features.
+ *
+ * Note: All exposed values are of type {@code String} for access through
+ * the common {@link Properties#getProperty} method (e.g. in configuration property
+ * resolution through {@link PropertyResourceConfigurer#setProperties(Properties)}).
+ * If this is not desirable, use {@link YamlMapFactoryBean} instead.
+ *
+ * The Properties created by this factory have nested paths for hierarchical
+ * objects, so for instance this YAML
*
* The default is singleton status, although this is only applied once
@@ -478,7 +484,6 @@ public boolean isLazyInit() {
return this.lazyInit;
}
-
/**
* Set the autowire mode. This determines whether any automagical detection
* and setting of bean references will happen. Default is AUTOWIRE_NO,
@@ -569,6 +574,12 @@ public String[] getDependsOn() {
/**
* Set whether this bean is a candidate for getting autowired into some other bean.
+ * Note that this flag is designed to only affect type-based autowiring.
+ * It does not affect explicit references by name, which will get resolved even
+ * if the specified bean is not marked as an autowire candidate. As a consequence,
+ * autowiring by name will nevertheless inject a bean if the name matches.
+ * @see #AUTOWIRE_BY_TYPE
+ * @see #AUTOWIRE_BY_NAME
*/
@Override
public void setAutowireCandidate(boolean autowireCandidate) {
@@ -585,7 +596,7 @@ public boolean isAutowireCandidate() {
/**
* Set whether this bean is a primary autowire candidate.
- * If this value is true for exactly one bean among multiple
+ * If this value is {@code true} for exactly one bean among multiple
* matching candidates, it will serve as a tie-breaker.
*/
@Override
@@ -595,8 +606,6 @@ public void setPrimary(boolean primary) {
/**
* Return whether this bean is a primary autowire candidate.
- * If this value is true for exactly one bean among multiple
- * matching candidates, it will serve as a tie-breaker.
*/
@Override
public boolean isPrimary() {
@@ -643,7 +652,6 @@ public void copyQualifiersFrom(AbstractBeanDefinition source) {
this.qualifiers.putAll(source.qualifiers);
}
-
/**
* Specify whether to allow access to non-public constructors and methods,
* for the case of externalized metadata pointing to those. The default is
@@ -683,6 +691,45 @@ public boolean isLenientConstructorResolution() {
return this.lenientConstructorResolution;
}
+ /**
+ * Specify the factory bean to use, if any.
+ * This the name of the bean to call the specified factory method on.
+ * @see #setFactoryMethodName
+ */
+ @Override
+ public void setFactoryBeanName(String factoryBeanName) {
+ this.factoryBeanName = factoryBeanName;
+ }
+
+ /**
+ * Return the factory bean name, if any.
+ */
+ @Override
+ public String getFactoryBeanName() {
+ return this.factoryBeanName;
+ }
+
+ /**
+ * Specify a factory method, if any. This method will be invoked with
+ * constructor arguments, or with no arguments if none are specified.
+ * The method will be invoked on the specified factory bean, if any,
+ * or otherwise as a static method on the local bean class.
+ * @see #setFactoryBeanName
+ * @see #setBeanClassName
+ */
+ @Override
+ public void setFactoryMethodName(String factoryMethodName) {
+ this.factoryMethodName = factoryMethodName;
+ }
+
+ /**
+ * Return a factory method, if any.
+ */
+ @Override
+ public String getFactoryMethodName() {
+ return this.factoryMethodName;
+ }
+
/**
* Specify constructor argument values for this bean.
*/
@@ -737,27 +784,6 @@ public MethodOverrides getMethodOverrides() {
return this.methodOverrides;
}
-
- @Override
- public void setFactoryBeanName(String factoryBeanName) {
- this.factoryBeanName = factoryBeanName;
- }
-
- @Override
- public String getFactoryBeanName() {
- return this.factoryBeanName;
- }
-
- @Override
- public void setFactoryMethodName(String factoryMethodName) {
- this.factoryMethodName = factoryMethodName;
- }
-
- @Override
- public String getFactoryMethodName() {
- return this.factoryMethodName;
- }
-
/**
* Set the name of the initializer method. The default is {@code null}
* in which case there is no initializer method.
@@ -822,7 +848,6 @@ public boolean isEnforceDestroyMethod() {
return this.enforceDestroyMethod;
}
-
/**
* Set whether this bean definition is 'synthetic', that is, not defined
* by the application itself (for example, an infrastructure bean such
@@ -855,7 +880,6 @@ public int getRole() {
return this.role;
}
-
/**
* Set a human-readable description of this bean definition.
*/
@@ -863,6 +887,9 @@ public void setDescription(String description) {
this.description = description;
}
+ /**
+ * Return a human-readable description of this bean definition.
+ */
@Override
public String getDescription() {
return this.description;
@@ -891,6 +918,10 @@ public void setResourceDescription(String resourceDescription) {
this.resource = new DescriptiveResource(resourceDescription);
}
+ /**
+ * Return a description of the resource that this bean definition
+ * came from (for the purpose of showing context in case of errors).
+ */
@Override
public String getResourceDescription() {
return (this.resource != null ? this.resource.getDescription() : null);
@@ -903,6 +934,12 @@ public void setOriginatingBeanDefinition(BeanDefinition originatingBd) {
this.resource = new BeanDefinitionResource(originatingBd);
}
+ /**
+ * Return the originating BeanDefinition, or {@code null} if none.
+ * Allows for retrieving the decorated bean definition, if any.
+ * Note that this method returns the immediate originator. Iterate through the
+ * originator chain to find the original BeanDefinition as defined by the user.
+ */
@Override
public BeanDefinition getOriginatingBeanDefinition() {
return (this.resource instanceof BeanDefinitionResource ?
@@ -981,7 +1018,6 @@ public Object clone() {
*/
public abstract AbstractBeanDefinition cloneBeanDefinition();
-
@Override
public boolean equals(Object other) {
if (this == other) {
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
index 62dfa38e42e8..1e021cc904f7 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -134,13 +134,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
private final Set For example, given a factory method with the following signature,
- * if {@code resolveReturnTypeForFactoryMethod()} is invoked with the reflected
+ * For example, given a factory method with the following signature, if
+ * {@code resolveReturnTypeForFactoryMethod()} is invoked with the reflected
* method for {@code creatProxy()} and an {@code Object[]} array containing
* {@code MyService.class}, {@code resolveReturnTypeForFactoryMethod()} will
* infer that the target return type is {@code MyService}.
@@ -184,9 +184,9 @@ public static Object resolveAutowiringValue(Object autowiringValue, Class> req
* @param method the method to introspect (never {@code null})
* @param args the arguments that will be supplied to the method when it is
* invoked (never {@code null})
- * @param classLoader the ClassLoader to resolve class names against, if necessary
- * (never {@code null})
- * @return the resolved target return type, the standard return type, or {@code null}
+ * @param classLoader the ClassLoader to resolve class names against,
+ * if necessary (never {@code null})
+ * @return the resolved target return type or the standard method return type
* @since 3.2.5
*/
public static Class> resolveReturnTypeForFactoryMethod(Method method, Object[] args, ClassLoader classLoader) {
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionBuilder.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionBuilder.java
index a1533835f95d..6eb6ec52405b 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionBuilder.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -159,13 +159,25 @@ public BeanDefinitionBuilder setParentName(String parentName) {
}
/**
- * Set the name of the factory method to use for this definition.
+ * Set the name of a static factory method to use for this definition,
+ * to be called on this bean's class.
*/
public BeanDefinitionBuilder setFactoryMethod(String factoryMethod) {
this.beanDefinition.setFactoryMethodName(factoryMethod);
return this;
}
+ /**
+ * Set the name of a non-static factory method to use for this definition,
+ * including the bean name of the factory instance to call the method on.
+ * @since 4.3.6
+ */
+ public BeanDefinitionBuilder setFactoryMethodOnBean(String factoryMethod, String factoryBean) {
+ this.beanDefinition.setFactoryMethodName(factoryMethod);
+ this.beanDefinition.setFactoryBeanName(factoryBean);
+ return this;
+ }
+
/**
* Add an indexed constructor arg value. The current index is tracked internally
* and all additions are at the present point.
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionDefaults.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionDefaults.java
index db7ccda80013..2ca5393169b3 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionDefaults.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionDefaults.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,7 +62,7 @@ public int getAutowireMode() {
}
public void setInitMethodName(String initMethodName) {
- this.initMethodName = (StringUtils.hasText(initMethodName)) ? initMethodName : null;
+ this.initMethodName = (StringUtils.hasText(initMethodName) ? initMethodName : null);
}
public String getInitMethodName() {
@@ -70,7 +70,7 @@ public String getInitMethodName() {
}
public void setDestroyMethodName(String destroyMethodName) {
- this.destroyMethodName = (StringUtils.hasText(destroyMethodName)) ? destroyMethodName : null;
+ this.destroyMethodName = (StringUtils.hasText(destroyMethodName) ? destroyMethodName : null);
}
public String getDestroyMethodName() {
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionReaderUtils.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionReaderUtils.java
index f56f0e527aac..8a745dab2c86 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionReaderUtils.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionReaderUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -69,6 +69,23 @@ public static AbstractBeanDefinition createBeanDefinition(
return bd;
}
+ /**
+ * Generate a bean name for the given top-level bean definition,
+ * unique within the given bean factory.
+ * @param beanDefinition the bean definition to generate a bean name for
+ * @param registry the bean factory that the definition is going to be
+ * registered with (to check for existing bean names)
+ * @return the generated bean name
+ * @throws BeanDefinitionStoreException if no unique name can be generated
+ * for the given bean definition
+ * @see #generateBeanName(BeanDefinition, BeanDefinitionRegistry, boolean)
+ */
+ public static String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry registry)
+ throws BeanDefinitionStoreException {
+
+ return generateBeanName(beanDefinition, registry, false);
+ }
+
/**
* Generate a bean name for the given bean definition, unique within the
* given bean factory.
@@ -117,22 +134,6 @@ else if (definition.getFactoryBeanName() != null) {
return id;
}
- /**
- * Generate a bean name for the given top-level bean definition,
- * unique within the given bean factory.
- * @param beanDefinition the bean definition to generate a bean name for
- * @param registry the bean factory that the definition is going to be
- * registered with (to check for existing bean names)
- * @return the generated bean name
- * @throws BeanDefinitionStoreException if no unique name can be generated
- * for the given bean definition
- */
- public static String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry registry)
- throws BeanDefinitionStoreException {
-
- return generateBeanName(beanDefinition, registry, false);
- }
-
/**
* Register the given bean definition with the given bean factory.
* @param definitionHolder the bean definition including name and aliases
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionRegistry.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionRegistry.java
index 326e1fb58c48..c99271bc32e0 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionRegistry.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionRegistry.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -55,6 +55,7 @@ public interface BeanDefinitionRegistry extends AliasRegistry {
* @throws BeanDefinitionStoreException if the BeanDefinition is invalid
* or if there is already a BeanDefinition for the specified bean name
* (and we are not allowed to override it)
+ * @see GenericBeanDefinition
* @see RootBeanDefinition
* @see ChildBeanDefinition
*/
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ChildBeanDefinition.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ChildBeanDefinition.java
index 87fc66ba879c..a6204ae2169f 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ChildBeanDefinition.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ChildBeanDefinition.java
@@ -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.
@@ -53,10 +53,7 @@ public class ChildBeanDefinition extends AbstractBeanDefinition {
* configured through its bean properties and configuration methods.
* @param parentName the name of the parent bean
* @see #setBeanClass
- * @see #setBeanClassName
* @see #setScope
- * @see #setAutowireMode
- * @see #setDependencyCheck
* @see #setConstructorArgumentValues
* @see #setPropertyValues
*/
@@ -174,9 +171,7 @@ public int hashCode() {
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("Child bean with parent '");
- sb.append(this.parentName).append("': ").append(super.toString());
- return sb.toString();
+ return "Child bean with parent '" + this.parentName + "': " + super.toString();
}
}
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
index 7c871d467e82..aa485efc7130 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
@@ -855,11 +855,11 @@ static InjectionPoint setCurrentInjectionPoint(InjectionPoint injectionPoint) {
*/
private static class ArgumentsHolder {
- public final Object rawArguments[];
+ public final Object[] rawArguments;
- public final Object arguments[];
+ public final Object[] arguments;
- public final Object preparedArguments[];
+ public final Object[] preparedArguments;
public boolean resolveNecessary = false;
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
index bb4ef59bf860..bb5ff2cf64a3 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,7 +32,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -44,6 +43,7 @@
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Provider;
+import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanCreationException;
@@ -62,11 +62,13 @@
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;
@@ -78,19 +80,17 @@
import org.springframework.util.StringUtils;
/**
- * Default implementation of the
- * {@link org.springframework.beans.factory.ListableBeanFactory} and
- * {@link BeanDefinitionRegistry} interfaces: a full-fledged bean factory
- * based on bean definition objects.
+ * Spring's default implementation of the {@link ConfigurableListableBeanFactory}
+ * and {@link BeanDefinitionRegistry} interfaces: a full-fledged bean factory
+ * based on bean definition metadata, extensible through post-processors.
*
* Typical usage is registering all bean definitions first (possibly read
- * from a bean definition file), before accessing beans. Bean definition lookup
+ * from a bean definition file), before accessing beans. Bean lookup by name
* is therefore an inexpensive operation in a local bean definition table,
- * operating on pre-built bean definition metadata objects.
+ * operating on pre-resolved bean definition metadata objects.
*
- * Can be used as a standalone bean factory, or as a superclass for custom
- * bean factories. Note that readers for specific bean definition formats are
- * typically implemented separately rather than as bean factory subclasses:
+ * Note that readers for specific bean definition formats are typically
+ * implemented separately rather than as bean factory subclasses:
* see for example {@link PropertiesBeanDefinitionReader} and
* {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.
*
@@ -107,9 +107,10 @@
* @author Phillip Webb
* @author Stephane Nicoll
* @since 16 April 2001
- * @see StaticListableBeanFactory
- * @see PropertiesBeanDefinitionReader
- * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
+ * @see #registerBeanDefinition
+ * @see #addBeanPostProcessor
+ * @see #getBean
+ * @see #resolveDependency
*/
@SuppressWarnings("serial")
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
@@ -265,6 +266,7 @@ public boolean isAllowEagerClassLoading() {
/**
* Set a {@link java.util.Comparator} for dependency Lists and arrays.
+ * @since 4.0
* @see org.springframework.core.OrderComparator
* @see org.springframework.core.annotation.AnnotationAwareOrderComparator
*/
@@ -274,6 +276,7 @@ public void setDependencyComparator(Comparator 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 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 The {@link #postProcessMergedBeanDefinition} method may for example introspect
* the bean definition in order to prepare some cached metadata before post-processing
- * actual instances of a bean. It is also allowed to modify the bean definition
- * but only for bean definition properties which are actually intended
- * for concurrent modification. Basically, this only applies to operations
- * defined on the {@link RootBeanDefinition} itself but not to the properties
- * of its base classes.
+ * actual instances of a bean. It is also allowed to modify the bean definition but
+ * only for definition properties which are actually intended for concurrent
+ * modification. Essentially, this only applies to operations defined on the
+ * {@link RootBeanDefinition} itself but not to the properties of its base classes.
*
* @author Juergen Hoeller
* @since 2.5
+ * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#getMergedBeanDefinition
*/
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java
index 91ad5d8e96cf..93da06b72f38 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java
@@ -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.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 @@
@SuppressWarnings("serial")
public class RootBeanDefinition extends AbstractBeanDefinition {
- boolean allowCaching = true;
-
private BeanDefinitionHolder decoratedDefinition;
- private volatile Class> targetType;
+ private AnnotatedElement qualifiedElement;
+
+ boolean allowCaching = true;
boolean isFactoryMethodUnique = false;
+ volatile ResolvableType targetType;
+
+ /** Package-visible field for caching the determined Class of a given bean definition */
+ volatile Class> resolvedTargetType;
+
+ /** Package-visible field for caching the return type of a generically typed factory method */
+ volatile ResolvableType factoryMethodReturnType;
+
+ /** Common lock for the four constructor fields below */
final Object constructorArgumentLock = new Object();
/** Package-visible field for caching the resolved constructor or factory method */
Object resolvedConstructorOrFactoryMethod;
- /** Package-visible field for caching the return type of a generically typed factory method */
- volatile Class> resolvedFactoryMethodReturnType;
-
/** Package-visible field that marks the constructor arguments as resolved */
boolean constructorArgumentsResolved = false;
@@ -73,6 +81,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
/** Package-visible field for caching partly prepared constructor arguments */
Object[] preparedConstructorArguments;
+ /** Common lock for the two post-processing fields below */
final Object postProcessingLock = new Object();
/** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied */
@@ -92,10 +101,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
* Create a new RootBeanDefinition, to be configured through its bean
* properties and configuration methods.
* @see #setBeanClass
- * @see #setBeanClassName
* @see #setScope
- * @see #setAutowireMode
- * @see #setDependencyCheck
* @see #setConstructorArgumentValues
* @see #setPropertyValues
*/
@@ -106,6 +112,7 @@ public RootBeanDefinition() {
/**
* Create a new RootBeanDefinition for a singleton.
* @param beanClass the class of the bean to instantiate
+ * @see #setBeanClass
*/
public RootBeanDefinition(Class> beanClass) {
super();
@@ -171,10 +178,11 @@ public RootBeanDefinition(String beanClassName, ConstructorArgumentValues cargs,
*/
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 +221,52 @@ public BeanDefinitionHolder getDecoratedDefinition() {
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);
}
/**
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java
index 4d29b95b6e2b..803810d834a2 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
package org.springframework.beans.factory.support;
-import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.DependencyDescriptor;
@@ -27,20 +26,27 @@
* @author Mark Fisher
* @author Juergen Hoeller
* @since 2.5
- * @see BeanDefinition#isAutowireCandidate()
*/
public class SimpleAutowireCandidateResolver implements AutowireCandidateResolver {
- /**
- * Determine if the provided bean definition is an autowire candidate.
- * To be considered a candidate the bean's autowire-candidate
- * attribute must not have been set to 'false'.
- */
@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
return bdHolder.getBeanDefinition().isAutowireCandidate();
}
+ /**
+ * Determine whether the given descriptor is effectively required.
+ * The default implementation checks {@link DependencyDescriptor#isRequired()}.
+ * @param descriptor the descriptor for the target method parameter or field
+ * @return whether the descriptor is marked as required or possibly indicating
+ * non-required status some other way (e.g. through a parameter annotation)
+ * @since 4.3.9
+ * @see DependencyDescriptor#isRequired()
+ */
+ public boolean isRequired(DependencyDescriptor descriptor) {
+ return descriptor.isRequired();
+ }
+
@Override
public Object getSuggestedValue(DependencyDescriptor descriptor) {
return null;
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
index 32866846deec..f5aee86bcfb7 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert;
+import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
@@ -134,12 +135,21 @@ public Object getBean(String name) throws BeansException {
@SuppressWarnings("unchecked")
public The default implementation uses {@link Node#getNamespaceURI}.
+ * Subclasses may override the default implementation to provide a
+ * different namespace identification mechanism.
* @param node the node
*/
public String getNamespaceURI(Node node) {
@@ -1487,8 +1488,10 @@ public String getNamespaceURI(Node node) {
}
/**
- * Ges the local name for the supplied {@link Node}. The default implementation calls {@link Node#getLocalName}.
- * Subclasses may override the default implementation to provide a different mechanism for getting the local name.
+ * Get the local name for the supplied {@link Node}.
+ * The default implementation calls {@link Node#getLocalName}.
+ * Subclasses may override the default implementation to provide a
+ * different mechanism for getting the local name.
* @param node the {@code Node}
*/
public String getLocalName(Node node) {
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/xml/BeansDtdResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/xml/BeansDtdResolver.java
index ad096bff7b8b..fe971fdca9a7 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/xml/BeansDtdResolver.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/xml/BeansDtdResolver.java
@@ -58,7 +58,7 @@ public InputSource resolveEntity(String publicId, String systemId) throws IOExce
"] and system ID [" + systemId + "]");
}
if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {
- int lastPathSeparator = systemId.lastIndexOf("/");
+ int lastPathSeparator = systemId.lastIndexOf('/');
int dtdNameStart = systemId.indexOf(DTD_NAME, lastPathSeparator);
if (dtdNameStart != -1) {
String dtdFile = DTD_FILENAME + DTD_EXTENSION;
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/xml/DefaultNamespaceHandlerResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/xml/DefaultNamespaceHandlerResolver.java
index fd7d64cc8cdd..e839303f513f 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/xml/DefaultNamespaceHandlerResolver.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/xml/DefaultNamespaceHandlerResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -147,16 +147,21 @@ else if (handlerOrClassName instanceof NamespaceHandler) {
* Load the specified NamespaceHandler mappings lazily.
*/
private Map
- * 1. BeanNameAware's {@code setBeanName}
- * 2. BeanClassLoaderAware's {@code setBeanClassLoader}
- * 3. BeanFactoryAware's {@code setBeanFactory}
- * 4. ResourceLoaderAware's {@code setResourceLoader}
- * (only applicable when running in an application context)
- * 5. ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
- * (only applicable when running in an application context)
- * 6. MessageSourceAware's {@code setMessageSource}
- * (only applicable when running in an application context)
- * 7. ApplicationContextAware's {@code setApplicationContext}
- * (only applicable when running in an application context)
- * 8. ServletContextAware's {@code setServletContext}
- * (only applicable when running in a web application context)
- * 9. {@code postProcessBeforeInitialization} methods of BeanPostProcessors
- * 10. InitializingBean's {@code afterPropertiesSet}
- * 11. a custom init-method definition
- * 12. {@code postProcessAfterInitialization} methods of BeanPostProcessors
+ * as far as possible. The full set of initialization methods and their standard order is:
+ *
+ *
*
- *
- * 1. DisposableBean's {@code destroy}
- * 2. a custom destroy-method definition
+ *
+ *
*
* @author Rod Johnson
* @author Juergen Hoeller
@@ -151,23 +158,6 @@ public interface BeanFactory {
*/
* foo:
@@ -62,6 +66,7 @@
* with the value in the second, but its nested values are merged.
*
* @author Dave Syer
+ * @author Juergen Hoeller
* @since 4.1
*/
public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean
* when mapped with
- * documentMatchers = YamlProcessor.mapMatcher({"environment": "prod"})
+ *
+ * setDocumentMatchers(properties ->
+ * ("prod".equals(properties.getProperty("environment")) ? MatchStatus.FOUND : MatchStatus.NOT_FOUND));
+ *
* would end up as
*
* environment=prod
* url=http://foo.bar.com
* name=My Cool App
- * url=http://dev.bar.com
*
- * @param matchers a map of keys to value patterns (regular expressions)
*/
public void setDocumentMatchers(DocumentMatcher... matchers) {
this.documentMatchers = Arrays.asList(matchers);
@@ -92,8 +94,7 @@ public void setDocumentMatchers(DocumentMatcher... matchers) {
/**
* Flag indicating that a document for which all the
* {@link #setDocumentMatchers(DocumentMatcher...) document matchers} abstain will
- * nevertheless match.
- * @param matchDefault the flag to set (default true)
+ * nevertheless match. Default is {@code true}.
*/
public void setMatchDefault(boolean matchDefault) {
this.matchDefault = matchDefault;
@@ -102,9 +103,7 @@ public void setMatchDefault(boolean matchDefault) {
/**
* Method to use for resolving resources. Each resource will be converted to a Map,
* so this property is used to decide which map entries to keep in the final output
- * from this factory.
- * @param resolutionMethod the resolution method to set (defaults to
- * {@link ResolutionMethod#OVERRIDE}).
+ * from this factory. Default is {@link ResolutionMethod#OVERRIDE}.
*/
public void setResolutionMethod(ResolutionMethod resolutionMethod) {
Assert.notNull(resolutionMethod, "ResolutionMethod must not be null");
@@ -199,7 +198,7 @@ private Map
* environments:
@@ -39,7 +49,7 @@
* name: My Cool App
*
*
- * is transformed into these Properties:
+ * is transformed into these properties:
*
*
* environments.dev.url=http://dev.bar.com
@@ -57,7 +67,7 @@
* - foo.bar.com
*
*
- * becomes Java Properties like this:
+ * becomes properties like this:
*
*
* servers[0]=dev.bar.com
@@ -66,6 +76,7 @@
*
* @author Dave Syer
* @author Stephane Nicoll
+ * @author Juergen Hoeller
* @since 4.1
*/
public class YamlPropertiesFactoryBean extends YamlProcessor implements FactoryBean