mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c9a55a34ce |
+1
-1
@@ -8,4 +8,4 @@ wiki page.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please see https://spring.io/security-policy.
|
||||
Please see https://pivotal.io/security.
|
||||
|
||||
+45
-45
@@ -3,8 +3,8 @@ plugins {
|
||||
id 'io.spring.nohttp' version '0.0.10'
|
||||
id "io.freefair.aspectj" version '6.2.0' apply false
|
||||
id 'org.jetbrains.dokka' version '1.5.0' apply false
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.5.32' apply false
|
||||
id "org.jetbrains.kotlin.plugin.serialization" version "1.5.32" apply false
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.5.31' apply false
|
||||
id "org.jetbrains.kotlin.plugin.serialization" version "1.5.31" apply false
|
||||
id 'org.asciidoctor.jvm.convert' version '3.3.2'
|
||||
id 'org.asciidoctor.jvm.pdf' version '3.3.2'
|
||||
id "org.unbroken-dome.xjc" version '2.0.0' apply false
|
||||
@@ -27,19 +27,19 @@ configure(allprojects) { project ->
|
||||
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom "com.fasterxml.jackson:jackson-bom:2.12.6"
|
||||
mavenBom "io.netty:netty-bom:4.1.72.Final"
|
||||
mavenBom "io.projectreactor:reactor-bom:2020.0.14"
|
||||
mavenBom "io.r2dbc:r2dbc-bom:Arabba-SR11"
|
||||
mavenBom "com.fasterxml.jackson:jackson-bom:2.12.5"
|
||||
mavenBom "io.netty:netty-bom:4.1.69.Final"
|
||||
mavenBom "io.projectreactor:reactor-bom:2020.0.12"
|
||||
mavenBom "io.r2dbc:r2dbc-bom:Arabba-SR10"
|
||||
mavenBom "io.rsocket:rsocket-bom:1.1.1"
|
||||
mavenBom "org.eclipse.jetty:jetty-bom:9.4.44.v20210927"
|
||||
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.5.32"
|
||||
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.5.31"
|
||||
mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.5.2"
|
||||
mavenBom "org.jetbrains.kotlinx:kotlinx-serialization-bom:1.2.2"
|
||||
mavenBom "org.junit:junit-bom:5.8.2"
|
||||
mavenBom "org.junit:junit-bom:5.8.1"
|
||||
}
|
||||
dependencies {
|
||||
dependencySet(group: 'org.apache.logging.log4j', version: '2.16.0') {
|
||||
dependencySet(group: 'org.apache.logging.log4j', version: '2.14.1') {
|
||||
entry 'log4j-api'
|
||||
entry 'log4j-core'
|
||||
entry 'log4j-jul'
|
||||
@@ -67,23 +67,23 @@ configure(allprojects) { project ->
|
||||
dependency "io.reactivex:rxjava:1.3.8"
|
||||
dependency "io.reactivex:rxjava-reactive-streams:1.2.1"
|
||||
dependency "io.reactivex.rxjava2:rxjava:2.2.21"
|
||||
dependency "io.reactivex.rxjava3:rxjava:3.1.3"
|
||||
dependency "io.smallrye.reactive:mutiny:1.2.0"
|
||||
dependency "io.reactivex.rxjava3:rxjava:3.1.1"
|
||||
dependency "io.smallrye.reactive:mutiny:1.1.1"
|
||||
dependency "io.projectreactor.tools:blockhound:1.0.6.RELEASE"
|
||||
|
||||
dependency "com.caucho:hessian:4.0.63"
|
||||
dependency "com.fasterxml:aalto-xml:1.3.0"
|
||||
dependency("com.fasterxml.woodstox:woodstox-core:6.2.7") {
|
||||
dependency("com.fasterxml.woodstox:woodstox-core:6.2.6") {
|
||||
exclude group: "stax", name: "stax-api"
|
||||
}
|
||||
dependency "com.google.code.gson:gson:2.8.9"
|
||||
dependency "com.google.protobuf:protobuf-java-util:3.19.1"
|
||||
dependency "com.google.code.gson:gson:2.8.8"
|
||||
dependency "com.google.protobuf:protobuf-java-util:3.18.0"
|
||||
dependency "com.googlecode.protobuf-java-format:protobuf-java-format:1.4"
|
||||
dependency("com.thoughtworks.xstream:xstream:1.4.18") {
|
||||
exclude group: "xpp3", name: "xpp3_min"
|
||||
exclude group: "xmlpull", name: "xmlpull"
|
||||
}
|
||||
dependency "org.apache.johnzon:johnzon-jsonb:1.2.15"
|
||||
dependency "org.apache.johnzon:johnzon-jsonb:1.2.14"
|
||||
dependency("org.codehaus.jettison:jettison:1.3.8") {
|
||||
exclude group: "stax", name: "stax-api"
|
||||
}
|
||||
@@ -92,10 +92,10 @@ configure(allprojects) { project ->
|
||||
entry 'jibx-run'
|
||||
}
|
||||
dependency "org.ogce:xpp3:1.1.6"
|
||||
dependency "org.yaml:snakeyaml:1.30"
|
||||
dependency "org.yaml:snakeyaml:1.29"
|
||||
|
||||
dependency "com.h2database:h2:1.4.200"
|
||||
dependency "com.github.ben-manes.caffeine:caffeine:2.9.3"
|
||||
dependency "com.github.ben-manes.caffeine:caffeine:2.9.2"
|
||||
dependency "com.github.librepdf:openpdf:1.3.26"
|
||||
dependency "com.rometools:rome:1.16.0"
|
||||
dependency "commons-io:commons-io:2.5"
|
||||
@@ -128,43 +128,43 @@ configure(allprojects) { project ->
|
||||
dependency "org.webjars:webjars-locator-core:0.48"
|
||||
dependency "org.webjars:underscorejs:1.8.3"
|
||||
|
||||
dependencySet(group: 'org.apache.tomcat', version: '9.0.56') {
|
||||
dependencySet(group: 'org.apache.tomcat', version: '9.0.53') {
|
||||
entry 'tomcat-util'
|
||||
entry('tomcat-websocket') {
|
||||
exclude group: "org.apache.tomcat", name: "tomcat-servlet-api"
|
||||
exclude group: "org.apache.tomcat", name: "tomcat-websocket-api"
|
||||
exclude group: "org.apache.tomcat", name: "tomcat-servlet-api"
|
||||
}
|
||||
}
|
||||
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.56') {
|
||||
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.53') {
|
||||
entry 'tomcat-embed-core'
|
||||
entry 'tomcat-embed-websocket'
|
||||
}
|
||||
dependencySet(group: 'io.undertow', version: '2.2.14.Final') {
|
||||
dependencySet(group: 'io.undertow', version: '2.2.12.Final') {
|
||||
entry 'undertow-core'
|
||||
entry('undertow-websockets-jsr') {
|
||||
exclude group: "org.jboss.spec.javax.websocket", name: "jboss-websocket-api_1.1_spec"
|
||||
}
|
||||
entry('undertow-servlet') {
|
||||
exclude group: "org.jboss.spec.javax.servlet", name: "jboss-servlet-api_4.0_spec"
|
||||
exclude group: "org.jboss.spec.javax.annotation", name: "jboss-annotations-api_1.3_spec"
|
||||
}
|
||||
entry('undertow-websockets-jsr') {
|
||||
exclude group: "org.jboss.spec.javax.websocket", name: "jboss-websocket-api_1.1_spec"
|
||||
}
|
||||
}
|
||||
|
||||
dependency "org.eclipse.jetty:jetty-reactive-httpclient:1.1.10"
|
||||
dependency 'org.apache.httpcomponents.client5:httpclient5:5.1.2'
|
||||
dependency 'org.apache.httpcomponents.core5:httpcore5-reactive:5.1.2'
|
||||
dependency("org.apache.httpcomponents:httpclient:4.5.13") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.apache.httpcomponents:httpasyncclient:4.1.5") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependencySet(group: 'com.squareup.okhttp3', version: '3.14.9') {
|
||||
entry 'okhttp'
|
||||
entry 'mockwebserver'
|
||||
}
|
||||
dependency("org.apache.httpcomponents:httpclient:4.5.13") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.apache.httpcomponents:httpasyncclient:4.1.4") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency 'org.apache.httpcomponents.client5:httpclient5:5.1'
|
||||
dependency 'org.apache.httpcomponents.core5:httpcore5-reactive:5.1.1'
|
||||
dependency "org.eclipse.jetty:jetty-reactive-httpclient:1.1.9"
|
||||
|
||||
dependency "org.jruby:jruby:9.2.20.1"
|
||||
dependency "org.jruby:jruby:9.2.19.0"
|
||||
dependency "org.python:jython-standalone:2.7.1"
|
||||
dependency "org.mozilla:rhino:1.7.11"
|
||||
|
||||
@@ -192,24 +192,24 @@ configure(allprojects) { project ->
|
||||
dependency "org.hamcrest:hamcrest:2.1"
|
||||
dependency "org.awaitility:awaitility:3.1.6"
|
||||
dependency "org.assertj:assertj-core:3.21.0"
|
||||
dependencySet(group: 'org.xmlunit', version: '2.8.3') {
|
||||
dependencySet(group: 'org.xmlunit', version: '2.8.2') {
|
||||
entry 'xmlunit-assertj'
|
||||
entry('xmlunit-matchers') {
|
||||
exclude group: "org.hamcrest", name: "hamcrest-core"
|
||||
}
|
||||
}
|
||||
dependencySet(group: 'org.mockito', version: '4.1.0') {
|
||||
dependencySet(group: 'org.mockito', version: '4.0.0') {
|
||||
entry('mockito-core') {
|
||||
exclude group: "org.hamcrest", name: "hamcrest-core"
|
||||
}
|
||||
entry 'mockito-junit-jupiter'
|
||||
}
|
||||
dependency "io.mockk:mockk:1.12.1"
|
||||
dependency "io.mockk:mockk:1.12.0"
|
||||
|
||||
dependency("net.sourceforge.htmlunit:htmlunit:2.55.0") {
|
||||
dependency("net.sourceforge.htmlunit:htmlunit:2.53.0") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.seleniumhq.selenium:htmlunit-driver:2.55.0") {
|
||||
dependency("org.seleniumhq.selenium:htmlunit-driver:2.53.0") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.seleniumhq.selenium:selenium-java:3.141.59") {
|
||||
@@ -237,7 +237,7 @@ configure(allprojects) { project ->
|
||||
|
||||
dependency "com.ibm.websphere:uow:6.0.2.17"
|
||||
dependency "com.jamonapi:jamon:2.82"
|
||||
dependency "joda-time:joda-time:2.10.13"
|
||||
dependency "joda-time:joda-time:2.10.10"
|
||||
dependency "org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.9"
|
||||
dependency "org.javamoney:moneta:1.3"
|
||||
|
||||
@@ -340,7 +340,7 @@ configure([rootProject] + javaProjects) { project ->
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
toolVersion = "9.2"
|
||||
toolVersion = "9.0"
|
||||
configDirectory.set(rootProject.file("src/checkstyle"))
|
||||
}
|
||||
|
||||
@@ -353,12 +353,12 @@ configure([rootProject] + javaProjects) { project ->
|
||||
testImplementation("io.mockk:mockk")
|
||||
testImplementation("org.assertj:assertj-core")
|
||||
// Pull in the latest JUnit 5 Launcher API to ensure proper support in IDEs.
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-suite-engine")
|
||||
testRuntimeOnly("org.apache.logging.log4j:log4j-core")
|
||||
testRuntimeOnly("org.apache.logging.log4j:log4j-jul")
|
||||
testRuntimeOnly("org.apache.logging.log4j:log4j-slf4j-impl")
|
||||
testRuntimeOnly("org.apache.logging.log4j:log4j-jul")
|
||||
// JSR-305 only used for non-required meta-annotations
|
||||
compileOnly("com.google.code.findbugs:jsr305")
|
||||
testCompileOnly("com.google.code.findbugs:jsr305")
|
||||
@@ -383,9 +383,9 @@ configure([rootProject] + javaProjects) { project ->
|
||||
"https://hc.apache.org/httpcomponents-client-5.1.x/current/httpclient5/apidocs/",
|
||||
"https://projectreactor.io/docs/test/release/api/",
|
||||
"https://junit.org/junit4/javadoc/4.13.2/",
|
||||
// Disabling linking to JUnit 5.8.2, since the `package-list` file no longer exists due to
|
||||
// Disabling linking to JUnit 5.8.1, since the `package-list` file no longer exists due to
|
||||
// https://github.com/junit-team/junit5/commit/67ad4e545518b0ce2b0e7c96df31a669866d5003.
|
||||
// "https://junit.org/junit5/docs/5.8.2/api/",
|
||||
// "https://junit.org/junit5/docs/5.8.1/api/",
|
||||
"https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/",
|
||||
"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/",
|
||||
"https://r2dbc.io/spec/0.8.5.RELEASE/api/"
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
version=5.3.14
|
||||
version=5.3.11
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
org.gradle.caching=true
|
||||
org.gradle.parallel=true
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "com.gradle.enterprise" version "3.7.2"
|
||||
id "com.gradle.enterprise" version "3.6.1"
|
||||
id "io.spring.ge.conventions" version "0.0.7"
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -45,10 +45,9 @@ import org.springframework.core.NativeDetector;
|
||||
* @see AdvisedSupport#setProxyTargetClass
|
||||
* @see AdvisedSupport#setInterfaces
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7930414337282325166L;
|
||||
|
||||
|
||||
@Override
|
||||
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -421,7 +421,11 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
* are unaffected by such changes.
|
||||
*/
|
||||
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
|
||||
if (!this.advisorChainInitialized && !ObjectUtils.isEmpty(this.interceptorNames)) {
|
||||
if (this.advisorChainInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
|
||||
if (this.beanFactory == null) {
|
||||
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
|
||||
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
|
||||
@@ -460,9 +464,9 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
addAdvisorOnChainCreation(advice);
|
||||
}
|
||||
}
|
||||
|
||||
this.advisorChainInitialized = true;
|
||||
}
|
||||
|
||||
this.advisorChainInitialized = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,8 +25,8 @@ import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.ThrowsAdvice;
|
||||
|
||||
/**
|
||||
* Adapter to enable {@link org.springframework.aop.ThrowsAdvice} to be used
|
||||
* in the Spring AOP framework.
|
||||
* Adapter to enable {@link org.springframework.aop.MethodBeforeAdvice}
|
||||
* to be used in the Spring AOP framework.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+2
-2
@@ -16,9 +16,9 @@
|
||||
</aop:aspect>
|
||||
</aop:config>
|
||||
|
||||
<bean id="getNameCounter" class="org.springframework.aop.testfixture.advice.CountingBeforeAdvice"/>
|
||||
<bean id="getNameCounter" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
<bean id="getAgeCounter" class="org.springframework.aop.testfixture.advice.CountingBeforeAdvice"/>
|
||||
<bean id="getAgeCounter" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
<bean id="testBean" class="org.springframework.beans.testfixture.beans.TestBean"/>
|
||||
|
||||
|
||||
+1
-1
@@ -9,6 +9,6 @@
|
||||
<aop:advisor advice-ref="countingAdvice" pointcut="within(org.springframework..*)"/>
|
||||
</aop:config>
|
||||
|
||||
<bean id="countingAdvice" class="org.springframework.aop.testfixture.advice.CountingBeforeAdvice"/>
|
||||
<bean id="countingAdvice" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
</beans>
|
||||
|
||||
+1
-1
@@ -10,6 +10,6 @@
|
||||
<aop:advisor advice-ref="countingAdvice" pointcut-ref="pc"/>
|
||||
</aop:config>
|
||||
|
||||
<bean id="countingAdvice" class="org.springframework.aop.testfixture.advice.CountingBeforeAdvice"/>
|
||||
<bean id="countingAdvice" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
</beans>
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
</aop:aspect>
|
||||
</aop:config>
|
||||
|
||||
<bean id="getAgeCounter" class="org.springframework.aop.testfixture.advice.CountingBeforeAdvice"/>
|
||||
<bean id="getAgeCounter" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
<bean id="testBean" class="org.springframework.beans.testfixture.beans.TestBean"/>
|
||||
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
</aop:aspect>
|
||||
</aop:config>
|
||||
|
||||
<bean id="getAgeCounter" class="org.springframework.aop.testfixture.advice.CountingBeforeAdvice"/>
|
||||
<bean id="getAgeCounter" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
<bean id="testBean" class="org.springframework.beans.testfixture.beans.TestBean"/>
|
||||
|
||||
|
||||
+6
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author 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.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
@@ -106,7 +107,10 @@ public class AspectJEnableCachingIsolatedTests {
|
||||
try {
|
||||
load(MultiCacheManagerConfigurer.class, EnableCachingConfig.class);
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
catch (BeanCreationException ex) {
|
||||
Throwable root = ex.getRootCause();
|
||||
boolean condition = root instanceof IllegalStateException;
|
||||
assertThat(condition).isTrue();
|
||||
assertThat(ex.getMessage().contains("implementations of CachingConfigurer")).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
+4
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -422,13 +422,10 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
}
|
||||
if (editor == null) {
|
||||
// Find editor for superclass or interface.
|
||||
for (Map.Entry<Class<?>, PropertyEditor> entry : this.customEditors.entrySet()) {
|
||||
if (editor != null) {
|
||||
break;
|
||||
}
|
||||
Class<?> key = entry.getKey();
|
||||
for (Iterator<Class<?>> it = this.customEditors.keySet().iterator(); it.hasNext() && editor == null;) {
|
||||
Class<?> key = it.next();
|
||||
if (key.isAssignableFrom(requiredType)) {
|
||||
editor = entry.getValue();
|
||||
editor = this.customEditors.get(key);
|
||||
// Cache editor for search type, to avoid the overhead
|
||||
// of repeated assignable-from checks.
|
||||
if (this.customEditorCache == null) {
|
||||
|
||||
@@ -214,7 +214,6 @@ public interface BeanFactory {
|
||||
/**
|
||||
* Return a provider for the specified bean, allowing for lazy on-demand retrieval
|
||||
* of instances, including availability and uniqueness options.
|
||||
* <p>For matching a generic type, consider {@link #getBeanProvider(ResolvableType)}.
|
||||
* @param requiredType type the bean must match; can be an interface or superclass
|
||||
* @return a corresponding provider handle
|
||||
* @since 5.1
|
||||
@@ -224,20 +223,13 @@ public interface BeanFactory {
|
||||
|
||||
/**
|
||||
* Return a provider for the specified bean, allowing for lazy on-demand retrieval
|
||||
* of instances, including availability and uniqueness options. This variant allows
|
||||
* for specifying a generic type to match, similar to reflective injection points
|
||||
* with generic type declarations in method/constructor parameters.
|
||||
* <p>Note that collections of beans are not supported here, in contrast to reflective
|
||||
* of instances, including availability and uniqueness options.
|
||||
* @param requiredType type the bean must match; can be a generic type declaration.
|
||||
* Note that collection types are not supported here, in contrast to reflective
|
||||
* injection points. For programmatically retrieving a list of beans matching a
|
||||
* specific type, specify the actual bean type as an argument here and subsequently
|
||||
* use {@link ObjectProvider#orderedStream()} or its lazy streaming/iteration options.
|
||||
* <p>Also, generics matching is strict here, as per the Java assignment rules.
|
||||
* For lenient fallback matching with unchecked semantics (similar to the ´unchecked´
|
||||
* Java compiler warning), consider calling {@link #getBeanProvider(Class)} with the
|
||||
* raw type as a second step if no full generic match is
|
||||
* {@link ObjectProvider#getIfAvailable() available} with this variant.
|
||||
* @return a corresponding provider handle
|
||||
* @param requiredType type the bean must match; can be a generic type declaration
|
||||
* @since 5.1
|
||||
* @see ObjectProvider#iterator()
|
||||
* @see ObjectProvider#stream()
|
||||
|
||||
+1
-23
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -353,31 +353,9 @@ public interface ListableBeanFactory extends BeanFactory {
|
||||
* @since 3.0
|
||||
* @see #getBeanNamesForAnnotation
|
||||
* @see #getBeansWithAnnotation
|
||||
* @see #getType(String)
|
||||
*/
|
||||
@Nullable
|
||||
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
|
||||
throws NoSuchBeanDefinitionException;
|
||||
|
||||
/**
|
||||
* Find an {@link Annotation} of {@code annotationType} on the specified bean,
|
||||
* traversing its interfaces and super classes if no annotation can be found on
|
||||
* the given class itself, as well as checking the bean's factory method (if any).
|
||||
* @param beanName the name of the bean to look for annotations on
|
||||
* @param annotationType the type of annotation to look for
|
||||
* (at class, interface or factory method level of the specified bean)
|
||||
* @param allowFactoryBeanInit whether a {@code FactoryBean} may get initialized
|
||||
* just for the purpose of determining its object type
|
||||
* @return the annotation of the given type if found, or {@code null} otherwise
|
||||
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
|
||||
* @since 5.3.14
|
||||
* @see #getBeanNamesForAnnotation
|
||||
* @see #getBeansWithAnnotation
|
||||
* @see #getType(String, boolean)
|
||||
*/
|
||||
@Nullable
|
||||
<A extends Annotation> A findAnnotationOnBean(
|
||||
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
|
||||
throws NoSuchBeanDefinitionException;
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -459,7 +459,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
return metadata;
|
||||
}
|
||||
|
||||
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
|
||||
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
|
||||
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
|
||||
return InjectionMetadata.EMPTY;
|
||||
}
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,7 +34,9 @@ import org.springframework.lang.Nullable;
|
||||
*
|
||||
* <p><b>NOTE:</b> This interface is a special purpose interface, mainly for
|
||||
* internal use within the framework. It is recommended to implement the plain
|
||||
* {@link BeanPostProcessor} interface as far as possible.
|
||||
* {@link BeanPostProcessor} interface as far as possible, or to derive from
|
||||
* {@link InstantiationAwareBeanPostProcessorAdapter} in order to be shielded
|
||||
* from extensions to this interface.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rod Johnson
|
||||
|
||||
+4
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -730,23 +730,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
|
||||
return findAnnotationOnBean(beanName, annotationType, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <A extends Annotation> A findAnnotationOnBean(
|
||||
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
|
||||
return findMergedAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit)
|
||||
return findMergedAnnotationOnBean(beanName, annotationType)
|
||||
.synthesize(MergedAnnotation::isPresent).orElse(null);
|
||||
}
|
||||
|
||||
private <A extends Annotation> MergedAnnotation<A> findMergedAnnotationOnBean(
|
||||
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit) {
|
||||
String beanName, Class<A> annotationType) {
|
||||
|
||||
Class<?> beanType = getType(beanName, allowFactoryBeanInit);
|
||||
Class<?> beanType = getType(beanName);
|
||||
if (beanType != null) {
|
||||
MergedAnnotation<A> annotation =
|
||||
MergedAnnotations.from(beanType, SearchStrategy.TYPE_HIERARCHY).get(annotationType);
|
||||
|
||||
+2
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -459,16 +459,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
|
||||
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
|
||||
return findAnnotationOnBean(beanName, annotationType, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <A extends Annotation> A findAnnotationOnBean(
|
||||
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
|
||||
Class<?> beanType = getType(beanName, allowFactoryBeanInit);
|
||||
Class<?> beanType = getType(beanName);
|
||||
return (beanType != null ? AnnotatedElementUtils.findMergedAnnotation(beanType, annotationType) : null);
|
||||
}
|
||||
|
||||
|
||||
+7
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,7 @@ import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.cache.annotation.AbstractCachingConfiguration;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.interceptor.CacheResolver;
|
||||
import org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource;
|
||||
import org.springframework.cache.jcache.interceptor.JCacheOperationSource;
|
||||
@@ -45,14 +46,11 @@ public abstract class AbstractJCacheConfiguration extends AbstractCachingConfigu
|
||||
|
||||
|
||||
@Override
|
||||
protected void useCachingConfigurer(CachingConfigurerSupplier cachingConfigurerSupplier) {
|
||||
super.useCachingConfigurer(cachingConfigurerSupplier);
|
||||
this.exceptionCacheResolver = cachingConfigurerSupplier.adapt(config -> {
|
||||
if (config instanceof JCacheConfigurer) {
|
||||
return ((JCacheConfigurer) config).exceptionCacheResolver();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
protected void useCachingConfigurer(CachingConfigurer config) {
|
||||
super.useCachingConfigurer(config);
|
||||
if (config instanceof JCacheConfigurer) {
|
||||
this.exceptionCacheResolver = ((JCacheConfigurer) config)::exceptionCacheResolver;
|
||||
}
|
||||
}
|
||||
|
||||
@Bean(name = "jCacheOperationSource")
|
||||
|
||||
Vendored
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -26,7 +26,8 @@ import org.springframework.lang.Nullable;
|
||||
* <p>To be implemented by classes annotated with
|
||||
* {@link org.springframework.cache.annotation.EnableCaching} that wish
|
||||
* or need to specify explicitly how exception caches are resolved for
|
||||
* annotation-driven cache management.
|
||||
* annotation-driven cache management. Consider extending {@link JCacheConfigurerSupport},
|
||||
* which provides a stub implementation of all interface methods.
|
||||
*
|
||||
* <p>See {@link org.springframework.cache.annotation.EnableCaching} for
|
||||
* general examples and context; see {@link #exceptionCacheResolver()} for
|
||||
@@ -35,6 +36,7 @@ import org.springframework.lang.Nullable;
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.1
|
||||
* @see CachingConfigurer
|
||||
* @see JCacheConfigurerSupport
|
||||
* @see org.springframework.cache.annotation.EnableCaching
|
||||
*/
|
||||
public interface JCacheConfigurer extends CachingConfigurer {
|
||||
@@ -58,8 +60,6 @@ public interface JCacheConfigurer extends CachingConfigurer {
|
||||
* See {@link org.springframework.cache.annotation.EnableCaching} for more complete examples.
|
||||
*/
|
||||
@Nullable
|
||||
default CacheResolver exceptionCacheResolver() {
|
||||
return null;
|
||||
}
|
||||
CacheResolver exceptionCacheResolver();
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -79,7 +79,7 @@ public abstract class AbstractFallbackJCacheOperationSource implements JCacheOpe
|
||||
|
||||
@Nullable
|
||||
private JCacheOperation<?> computeCacheOperation(Method method, @Nullable Class<?> targetClass) {
|
||||
// Don't allow non-public methods, as configured.
|
||||
// Don't allow no-public methods as required.
|
||||
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+1
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,8 +39,6 @@ import org.springframework.lang.Nullable;
|
||||
* Subclass of Quartz's {@link JobStoreCMT} class that delegates to a Spring-managed
|
||||
* {@link DataSource} instead of using a Quartz-managed JDBC connection pool.
|
||||
* This JobStore will be used if SchedulerFactoryBean's "dataSource" property is set.
|
||||
* You may also configure it explicitly, possibly as a custom subclass of this
|
||||
* {@code LocalDataSourceJobStore} or as an equivalent {@code JobStoreCMT} variant.
|
||||
*
|
||||
* <p>Supports both transactional and non-transactional DataSource access.
|
||||
* With a non-XA DataSource and local Spring transactions, a single DataSource
|
||||
@@ -60,8 +58,6 @@ import org.springframework.lang.Nullable;
|
||||
* @since 1.1
|
||||
* @see SchedulerFactoryBean#setDataSource
|
||||
* @see SchedulerFactoryBean#setNonTransactionalDataSource
|
||||
* @see SchedulerFactoryBean#getConfigTimeDataSource()
|
||||
* @see SchedulerFactoryBean#getConfigTimeNonTransactionalDataSource()
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection
|
||||
*/
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -310,11 +310,9 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
|
||||
|
||||
/**
|
||||
* Set the default {@link DataSource} to be used by the Scheduler.
|
||||
* If set, this will override corresponding settings in Quartz properties.
|
||||
* <p>Note: If this is set, the Quartz settings should not define
|
||||
* a job store "dataSource" to avoid meaningless double configuration.
|
||||
* Also, do not define a "org.quartz.jobStore.class" property at all.
|
||||
* (You may explicitly define Spring's {@link LocalDataSourceJobStore}
|
||||
* but that's the default when using this method anyway.)
|
||||
* <p>A Spring-specific subclass of Quartz' JobStoreCMT will be used.
|
||||
* It is therefore strongly recommended to perform all operations on
|
||||
* the Scheduler within Spring-managed (or plain JTA) transactions.
|
||||
@@ -572,7 +570,7 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
|
||||
|
||||
CollectionUtils.mergePropertiesIntoMap(this.quartzProperties, mergedProps);
|
||||
if (this.dataSource != null) {
|
||||
mergedProps.putIfAbsent(StdSchedulerFactory.PROP_JOB_STORE_CLASS, LocalDataSourceJobStore.class.getName());
|
||||
mergedProps.setProperty(StdSchedulerFactory.PROP_JOB_STORE_CLASS, LocalDataSourceJobStore.class.getName());
|
||||
}
|
||||
|
||||
// Determine scheduler name across local settings and Quartz properties...
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,7 +26,7 @@ import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.interceptor.KeyGenerator;
|
||||
import org.springframework.cache.interceptor.SimpleKeyGenerator;
|
||||
@@ -104,7 +104,7 @@ public class JCacheEhCacheAnnotationTests extends AbstractCacheAnnotationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class EnableCachingConfig implements CachingConfigurer {
|
||||
static class EnableCachingConfig extends CachingConfigurerSupport {
|
||||
|
||||
@Autowired
|
||||
CachingProvider cachingProvider;
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -180,7 +180,7 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
public static class EmptyConfigSupportConfig implements JCacheConfigurer {
|
||||
public static class EmptyConfigSupportConfig extends JCacheConfigurerSupport {
|
||||
@Bean
|
||||
public CacheManager cm() {
|
||||
return new NoOpCacheManager();
|
||||
@@ -190,7 +190,7 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class FullCachingConfigSupport implements JCacheConfigurer {
|
||||
static class FullCachingConfigSupport extends JCacheConfigurerSupport {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
@@ -220,7 +220,7 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class NoExceptionCacheResolverConfig implements JCacheConfigurer {
|
||||
static class NoExceptionCacheResolverConfig extends JCacheConfigurerSupport {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,7 +34,7 @@ import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.interceptor.CacheErrorHandler;
|
||||
import org.springframework.cache.interceptor.SimpleKeyGenerator;
|
||||
import org.springframework.cache.jcache.config.JCacheConfigurer;
|
||||
import org.springframework.cache.jcache.config.JCacheConfigurerSupport;
|
||||
import org.springframework.cache.support.SimpleCacheManager;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -141,7 +141,7 @@ public class JCacheErrorHandlerTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class Config implements JCacheConfigurer {
|
||||
static class Config extends JCacheConfigurerSupport {
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,7 +34,7 @@ import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||
import org.springframework.cache.interceptor.KeyGenerator;
|
||||
import org.springframework.cache.interceptor.SimpleKey;
|
||||
import org.springframework.cache.interceptor.SimpleKeyGenerator;
|
||||
import org.springframework.cache.jcache.config.JCacheConfigurer;
|
||||
import org.springframework.cache.jcache.config.JCacheConfigurerSupport;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -97,7 +97,7 @@ public class JCacheKeyGeneratorTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class Config implements JCacheConfigurer {
|
||||
static class Config extends JCacheConfigurerSupport {
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
@@ -151,7 +151,7 @@ public class JCacheKeyGeneratorTests {
|
||||
@Override
|
||||
public Object generate(Object target, Method method, Object... params) {
|
||||
assertThat(Arrays.equals(expectedParams, params)).as("Unexpected parameters: expected: "
|
||||
+ Arrays.toString(this.expectedParams) + " but got: " + Arrays.toString(params)).isTrue();
|
||||
+ Arrays.toString(this.expectedParams) + " but got: " + Arrays.toString(params)).isTrue();
|
||||
return new SimpleKey(params);
|
||||
}
|
||||
}
|
||||
|
||||
+24
-57
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,6 @@ package org.springframework.scheduling.quartz;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@@ -31,7 +30,6 @@ import org.quartz.SchedulerContext;
|
||||
import org.quartz.SchedulerFactory;
|
||||
import org.quartz.impl.JobDetailImpl;
|
||||
import org.quartz.impl.SchedulerRepository;
|
||||
import org.quartz.impl.jdbcjobstore.JobStoreTX;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
@@ -42,8 +40,6 @@ import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.core.testfixture.EnabledForTestGroups;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
@@ -61,10 +57,10 @@ import static org.springframework.core.testfixture.TestGroup.LONG_RUNNING;
|
||||
* @author Sam Brannen
|
||||
* @since 20.02.2004
|
||||
*/
|
||||
class QuartzSupportTests {
|
||||
public class QuartzSupportTests {
|
||||
|
||||
@Test
|
||||
void schedulerFactoryBeanWithApplicationContext() throws Exception {
|
||||
public void schedulerFactoryBeanWithApplicationContext() throws Exception {
|
||||
TestBean tb = new TestBean("tb", 99);
|
||||
StaticApplicationContext ac = new StaticApplicationContext();
|
||||
|
||||
@@ -101,7 +97,7 @@ class QuartzSupportTests {
|
||||
|
||||
@Test
|
||||
@EnabledForTestGroups(LONG_RUNNING)
|
||||
void schedulerWithTaskExecutor() throws Exception {
|
||||
public void schedulerWithTaskExecutor() throws Exception {
|
||||
CountingTaskExecutor taskExecutor = new CountingTaskExecutor();
|
||||
DummyJob.count = 0;
|
||||
|
||||
@@ -134,7 +130,7 @@ class QuartzSupportTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
void jobDetailWithRunnableInsteadOfJob() {
|
||||
public void jobDetailWithRunnableInsteadOfJob() {
|
||||
JobDetailImpl jobDetail = new JobDetailImpl();
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
jobDetail.setJobClass((Class) DummyRunnable.class));
|
||||
@@ -142,7 +138,7 @@ class QuartzSupportTests {
|
||||
|
||||
@Test
|
||||
@EnabledForTestGroups(LONG_RUNNING)
|
||||
void schedulerWithQuartzJobBean() throws Exception {
|
||||
public void schedulerWithQuartzJobBean() throws Exception {
|
||||
DummyJob.param = 0;
|
||||
DummyJob.count = 0;
|
||||
|
||||
@@ -175,7 +171,7 @@ class QuartzSupportTests {
|
||||
|
||||
@Test
|
||||
@EnabledForTestGroups(LONG_RUNNING)
|
||||
void schedulerWithSpringBeanJobFactory() throws Exception {
|
||||
public void schedulerWithSpringBeanJobFactory() throws Exception {
|
||||
DummyJob.param = 0;
|
||||
DummyJob.count = 0;
|
||||
|
||||
@@ -210,7 +206,7 @@ class QuartzSupportTests {
|
||||
|
||||
@Test
|
||||
@EnabledForTestGroups(LONG_RUNNING)
|
||||
void schedulerWithSpringBeanJobFactoryAndParamMismatchNotIgnored() throws Exception {
|
||||
public void schedulerWithSpringBeanJobFactoryAndParamMismatchNotIgnored() throws Exception {
|
||||
DummyJob.param = 0;
|
||||
DummyJob.count = 0;
|
||||
|
||||
@@ -246,7 +242,7 @@ class QuartzSupportTests {
|
||||
|
||||
@Test
|
||||
@EnabledForTestGroups(LONG_RUNNING)
|
||||
void schedulerWithSpringBeanJobFactoryAndQuartzJobBean() throws Exception {
|
||||
public void schedulerWithSpringBeanJobFactoryAndQuartzJobBean() throws Exception {
|
||||
DummyJobBean.param = 0;
|
||||
DummyJobBean.count = 0;
|
||||
|
||||
@@ -280,7 +276,7 @@ class QuartzSupportTests {
|
||||
|
||||
@Test
|
||||
@EnabledForTestGroups(LONG_RUNNING)
|
||||
void schedulerWithSpringBeanJobFactoryAndJobSchedulingData() throws Exception {
|
||||
public void schedulerWithSpringBeanJobFactoryAndJobSchedulingData() throws Exception {
|
||||
DummyJob.param = 0;
|
||||
DummyJob.count = 0;
|
||||
|
||||
@@ -298,7 +294,7 @@ class QuartzSupportTests {
|
||||
}
|
||||
|
||||
@Test // SPR-772
|
||||
void multipleSchedulers() throws Exception {
|
||||
public void multipleSchedulers() throws Exception {
|
||||
try (ClassPathXmlApplicationContext ctx = context("multipleSchedulers.xml")) {
|
||||
Scheduler scheduler1 = (Scheduler) ctx.getBean("scheduler1");
|
||||
Scheduler scheduler2 = (Scheduler) ctx.getBean("scheduler2");
|
||||
@@ -309,7 +305,7 @@ class QuartzSupportTests {
|
||||
}
|
||||
|
||||
@Test // SPR-16884
|
||||
void multipleSchedulersWithQuartzProperties() throws Exception {
|
||||
public void multipleSchedulersWithQuartzProperties() throws Exception {
|
||||
try (ClassPathXmlApplicationContext ctx = context("multipleSchedulersWithQuartzProperties.xml")) {
|
||||
Scheduler scheduler1 = (Scheduler) ctx.getBean("scheduler1");
|
||||
Scheduler scheduler2 = (Scheduler) ctx.getBean("scheduler2");
|
||||
@@ -321,13 +317,12 @@ class QuartzSupportTests {
|
||||
|
||||
@Test
|
||||
@EnabledForTestGroups(LONG_RUNNING)
|
||||
void twoAnonymousMethodInvokingJobDetailFactoryBeans() throws Exception {
|
||||
public void twoAnonymousMethodInvokingJobDetailFactoryBeans() throws Exception {
|
||||
Thread.sleep(3000);
|
||||
try (ClassPathXmlApplicationContext ctx = context("multipleAnonymousMethodInvokingJobDetailFB.xml")) {
|
||||
QuartzTestBean exportService = (QuartzTestBean) ctx.getBean("exportService");
|
||||
QuartzTestBean importService = (QuartzTestBean) ctx.getBean("importService");
|
||||
|
||||
Thread.sleep(400);
|
||||
|
||||
assertThat(exportService.getImportCount()).as("doImport called exportService").isEqualTo(0);
|
||||
assertThat(exportService.getExportCount()).as("doExport not called on exportService").isEqualTo(2);
|
||||
assertThat(importService.getImportCount()).as("doImport not called on importService").isEqualTo(2);
|
||||
@@ -337,13 +332,12 @@ class QuartzSupportTests {
|
||||
|
||||
@Test
|
||||
@EnabledForTestGroups(LONG_RUNNING)
|
||||
void schedulerAccessorBean() throws Exception {
|
||||
public void schedulerAccessorBean() throws Exception {
|
||||
Thread.sleep(3000);
|
||||
try (ClassPathXmlApplicationContext ctx = context("schedulerAccessorBean.xml")) {
|
||||
QuartzTestBean exportService = (QuartzTestBean) ctx.getBean("exportService");
|
||||
QuartzTestBean importService = (QuartzTestBean) ctx.getBean("importService");
|
||||
|
||||
Thread.sleep(400);
|
||||
|
||||
assertThat(exportService.getImportCount()).as("doImport called exportService").isEqualTo(0);
|
||||
assertThat(exportService.getExportCount()).as("doExport not called on exportService").isEqualTo(2);
|
||||
assertThat(importService.getImportCount()).as("doImport not called on importService").isEqualTo(2);
|
||||
@@ -353,7 +347,7 @@ class QuartzSupportTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
void schedulerAutoStartsOnContextRefreshedEventByDefault() throws Exception {
|
||||
public void schedulerAutoStartsOnContextRefreshedEventByDefault() throws Exception {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
context.registerBeanDefinition("scheduler", new RootBeanDefinition(SchedulerFactoryBean.class));
|
||||
Scheduler bean = context.getBean("scheduler", Scheduler.class);
|
||||
@@ -364,7 +358,7 @@ class QuartzSupportTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
void schedulerAutoStartupFalse() throws Exception {
|
||||
public void schedulerAutoStartupFalse() throws Exception {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(SchedulerFactoryBean.class)
|
||||
.addPropertyValue("autoStartup", false).getBeanDefinition();
|
||||
@@ -376,7 +370,7 @@ class QuartzSupportTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void schedulerRepositoryExposure() throws Exception {
|
||||
public void schedulerRepositoryExposure() throws Exception {
|
||||
try (ClassPathXmlApplicationContext ctx = context("schedulerRepositoryExposure.xml")) {
|
||||
assertThat(ctx.getBean("scheduler")).isSameAs(SchedulerRepository.getInstance().lookup("myScheduler"));
|
||||
}
|
||||
@@ -387,7 +381,7 @@ class QuartzSupportTests {
|
||||
* TODO: Against Quartz 2.2, this test's job doesn't actually execute anymore...
|
||||
*/
|
||||
@Test
|
||||
void schedulerWithHsqlDataSource() throws Exception {
|
||||
public void schedulerWithHsqlDataSource() throws Exception {
|
||||
DummyJob.param = 0;
|
||||
DummyJob.count = 0;
|
||||
|
||||
@@ -402,36 +396,12 @@ class QuartzSupportTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
void schedulerFactoryBeanWithCustomJobStore() throws Exception {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
|
||||
String dbName = "mydb";
|
||||
EmbeddedDatabase database = new EmbeddedDatabaseBuilder().setName(dbName).build();
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("org.quartz.jobStore.class", JobStoreTX.class.getName());
|
||||
properties.setProperty("org.quartz.jobStore.dataSource", dbName);
|
||||
|
||||
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(SchedulerFactoryBean.class)
|
||||
.addPropertyValue("autoStartup", false)
|
||||
.addPropertyValue("dataSource", database)
|
||||
.addPropertyValue("quartzProperties", properties)
|
||||
.getBeanDefinition();
|
||||
context.registerBeanDefinition("scheduler", beanDefinition);
|
||||
|
||||
Scheduler scheduler = context.getBean(Scheduler.class);
|
||||
|
||||
assertThat(scheduler.getMetaData().getJobStoreClass()).isEqualTo(JobStoreTX.class);
|
||||
}
|
||||
|
||||
private ClassPathXmlApplicationContext context(String path) {
|
||||
return new ClassPathXmlApplicationContext(path, getClass());
|
||||
}
|
||||
|
||||
|
||||
private static class CountingTaskExecutor implements TaskExecutor {
|
||||
public static class CountingTaskExecutor implements TaskExecutor {
|
||||
|
||||
private int count;
|
||||
|
||||
@@ -443,14 +413,12 @@ class QuartzSupportTests {
|
||||
}
|
||||
|
||||
|
||||
private static class DummyJob implements Job {
|
||||
public static class DummyJob implements Job {
|
||||
|
||||
private static int param;
|
||||
|
||||
private static int count;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
// Must be public
|
||||
public void setParam(int value) {
|
||||
if (param > 0) {
|
||||
throw new IllegalStateException("Param already set");
|
||||
@@ -465,13 +433,12 @@ class QuartzSupportTests {
|
||||
}
|
||||
|
||||
|
||||
private static class DummyJobBean extends QuartzJobBean {
|
||||
public static class DummyJobBean extends QuartzJobBean {
|
||||
|
||||
private static int param;
|
||||
|
||||
private static int count;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setParam(int value) {
|
||||
if (param > 0) {
|
||||
throw new IllegalStateException("Param already set");
|
||||
@@ -486,7 +453,7 @@ class QuartzSupportTests {
|
||||
}
|
||||
|
||||
|
||||
private static class DummyRunnable implements Runnable {
|
||||
public static class DummyRunnable implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@
|
||||
<property name="targetMethod" value="doExport"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="repeatInterval" value="200"/>
|
||||
<property name="repeatInterval" value="1000"/>
|
||||
<property name="repeatCount" value="1"/>
|
||||
</bean>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<property name="targetMethod" value="doImport"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="repeatInterval" value="200"/>
|
||||
<property name="repeatInterval" value="1000"/>
|
||||
<property name="repeatCount" value="1"/>
|
||||
</bean>
|
||||
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@
|
||||
<property name="targetMethod" value="doExport"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="repeatInterval" value="200"/>
|
||||
<property name="repeatInterval" value="1000"/>
|
||||
<property name="repeatCount" value="1"/>
|
||||
</bean>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<property name="targetMethod" value="doImport"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="repeatInterval" value="200"/>
|
||||
<property name="repeatInterval" value="1000"/>
|
||||
<property name="repeatCount" value="1"/>
|
||||
</bean>
|
||||
|
||||
|
||||
Vendored
+21
-56
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,12 +16,9 @@
|
||||
|
||||
package org.springframework.cache.annotation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.interceptor.CacheErrorHandler;
|
||||
@@ -33,7 +30,6 @@ import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.function.SingletonSupplier;
|
||||
|
||||
/**
|
||||
* Abstract base {@code @Configuration} class providing common structure
|
||||
@@ -67,67 +63,36 @@ public abstract class AbstractCachingConfiguration implements ImportAware {
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
this.enableCaching = AnnotationAttributes.fromMap(
|
||||
importMetadata.getAnnotationAttributes(EnableCaching.class.getName()));
|
||||
importMetadata.getAnnotationAttributes(EnableCaching.class.getName(), false));
|
||||
if (this.enableCaching == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"@EnableCaching is not present on importing class " + importMetadata.getClassName());
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
void setConfigurers(ObjectProvider<CachingConfigurer> configurers) {
|
||||
Supplier<CachingConfigurer> configurer = () -> {
|
||||
List<CachingConfigurer> candidates = configurers.stream().collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(candidates)) {
|
||||
return null;
|
||||
}
|
||||
if (candidates.size() > 1) {
|
||||
throw new IllegalStateException(candidates.size() + " implementations of " +
|
||||
"CachingConfigurer were found when only 1 was expected. " +
|
||||
"Refactor the configuration such that CachingConfigurer is " +
|
||||
"implemented only once or not at all.");
|
||||
}
|
||||
return candidates.get(0);
|
||||
};
|
||||
useCachingConfigurer(new CachingConfigurerSupplier(configurer));
|
||||
@Autowired(required = false)
|
||||
void setConfigurers(Collection<CachingConfigurer> configurers) {
|
||||
if (CollectionUtils.isEmpty(configurers)) {
|
||||
return;
|
||||
}
|
||||
if (configurers.size() > 1) {
|
||||
throw new IllegalStateException(configurers.size() + " implementations of " +
|
||||
"CachingConfigurer were found when only 1 was expected. " +
|
||||
"Refactor the configuration such that CachingConfigurer is " +
|
||||
"implemented only once or not at all.");
|
||||
}
|
||||
CachingConfigurer configurer = configurers.iterator().next();
|
||||
useCachingConfigurer(configurer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the configuration from the nominated {@link CachingConfigurer}.
|
||||
*/
|
||||
protected void useCachingConfigurer(CachingConfigurerSupplier cachingConfigurerSupplier) {
|
||||
this.cacheManager = cachingConfigurerSupplier.adapt(CachingConfigurer::cacheManager);
|
||||
this.cacheResolver = cachingConfigurerSupplier.adapt(CachingConfigurer::cacheResolver);
|
||||
this.keyGenerator = cachingConfigurerSupplier.adapt(CachingConfigurer::keyGenerator);
|
||||
this.errorHandler = cachingConfigurerSupplier.adapt(CachingConfigurer::errorHandler);
|
||||
}
|
||||
|
||||
|
||||
protected static class CachingConfigurerSupplier {
|
||||
|
||||
private final Supplier<CachingConfigurer> supplier;
|
||||
|
||||
public CachingConfigurerSupplier(Supplier<CachingConfigurer> supplier) {
|
||||
this.supplier = SingletonSupplier.of(supplier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapt the {@link CachingConfigurer} supplier to another supplier
|
||||
* provided by the specified mapping function. If the underlying
|
||||
* {@link CachingConfigurer} is {@code null}, {@code null} is returned
|
||||
* and the mapping function is not invoked.
|
||||
* @param provider the provider to use to adapt the supplier
|
||||
* @param <T> the type of the supplier
|
||||
* @return another supplier mapped by the specified function
|
||||
*/
|
||||
@Nullable
|
||||
public <T> Supplier<T> adapt(Function<CachingConfigurer, T> provider) {
|
||||
return () -> {
|
||||
CachingConfigurer cachingConfigurer = this.supplier.get();
|
||||
return (cachingConfigurer != null ? provider.apply(cachingConfigurer) : null);
|
||||
};
|
||||
}
|
||||
|
||||
protected void useCachingConfigurer(CachingConfigurer config) {
|
||||
this.cacheManager = config::cacheManager;
|
||||
this.cacheResolver = config::cacheResolver;
|
||||
this.keyGenerator = config::keyGenerator;
|
||||
this.errorHandler = config::errorHandler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -26,7 +26,8 @@ import org.springframework.lang.Nullable;
|
||||
* Interface to be implemented by @{@link org.springframework.context.annotation.Configuration
|
||||
* Configuration} classes annotated with @{@link EnableCaching} that wish or need to
|
||||
* specify explicitly how caches are resolved and how keys are generated for annotation-driven
|
||||
* cache management.
|
||||
* cache management. Consider extending {@link CachingConfigurerSupport}, which provides a
|
||||
* stub implementation of all interface methods.
|
||||
*
|
||||
* <p>See @{@link EnableCaching} for general examples and context; see
|
||||
* {@link #cacheManager()}, {@link #cacheResolver()} and {@link #keyGenerator()}
|
||||
@@ -36,6 +37,7 @@ import org.springframework.lang.Nullable;
|
||||
* @author Stephane Nicoll
|
||||
* @since 3.1
|
||||
* @see EnableCaching
|
||||
* @see CachingConfigurerSupport
|
||||
*/
|
||||
public interface CachingConfigurer {
|
||||
|
||||
@@ -62,9 +64,7 @@ public interface CachingConfigurer {
|
||||
* See @{@link EnableCaching} for more complete examples.
|
||||
*/
|
||||
@Nullable
|
||||
default CacheManager cacheManager() {
|
||||
return null;
|
||||
}
|
||||
CacheManager cacheManager();
|
||||
|
||||
/**
|
||||
* Return the {@link CacheResolver} bean to use to resolve regular caches for
|
||||
@@ -89,9 +89,7 @@ public interface CachingConfigurer {
|
||||
* See {@link EnableCaching} for more complete examples.
|
||||
*/
|
||||
@Nullable
|
||||
default CacheResolver cacheResolver() {
|
||||
return null;
|
||||
}
|
||||
CacheResolver cacheResolver();
|
||||
|
||||
/**
|
||||
* Return the key generator bean to use for annotation-driven cache management.
|
||||
@@ -112,9 +110,7 @@ public interface CachingConfigurer {
|
||||
* See @{@link EnableCaching} for more complete examples.
|
||||
*/
|
||||
@Nullable
|
||||
default KeyGenerator keyGenerator() {
|
||||
return null;
|
||||
}
|
||||
KeyGenerator keyGenerator();
|
||||
|
||||
/**
|
||||
* Return the {@link CacheErrorHandler} to use to handle cache-related errors.
|
||||
@@ -137,8 +133,6 @@ public interface CachingConfigurer {
|
||||
* See @{@link EnableCaching} for more complete examples.
|
||||
*/
|
||||
@Nullable
|
||||
default CacheErrorHandler errorHandler() {
|
||||
return null;
|
||||
}
|
||||
CacheErrorHandler errorHandler();
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -124,7 +124,7 @@ public abstract class AbstractFallbackCacheOperationSource implements CacheOpera
|
||||
|
||||
@Nullable
|
||||
private Collection<CacheOperation> computeCacheOperations(Method method, @Nullable Class<?> targetClass) {
|
||||
// Don't allow non-public methods, as configured.
|
||||
// Don't allow no-public methods as required.
|
||||
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,10 +47,9 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* <p>If the annotation's value doesn't indicate a bean name, an appropriate
|
||||
* name will be built based on the short name of the class (with the first
|
||||
* letter lower-cased), unless the two first letters are uppercase. For example:
|
||||
* letter lower-cased). For example:
|
||||
*
|
||||
* <pre class="code">com.xyz.FooServiceImpl -> fooServiceImpl</pre>
|
||||
* <pre class="code">com.xyz.URLFooServiceImpl -> URLFooServiceImpl</pre>
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Mark Fisher
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -282,7 +282,7 @@ public abstract class AnnotationConfigUtils {
|
||||
|
||||
@Nullable
|
||||
static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, String annotationClassName) {
|
||||
return AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClassName));
|
||||
return AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClassName, false));
|
||||
}
|
||||
|
||||
static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata,
|
||||
@@ -298,10 +298,10 @@ public abstract class AnnotationConfigUtils {
|
||||
Set<AnnotationAttributes> result = new LinkedHashSet<>();
|
||||
|
||||
// Direct annotation present?
|
||||
addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName));
|
||||
addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName, false));
|
||||
|
||||
// Container annotation present?
|
||||
Map<String, Object> container = metadata.getAnnotationAttributes(containerClassName);
|
||||
Map<String, Object> container = metadata.getAnnotationAttributes(containerClassName, false);
|
||||
if (container != null && container.containsKey("value")) {
|
||||
for (Map<String, Object> containedAttributes : (Map<String, Object>[]) container.get("value")) {
|
||||
addAttributesIfNotNull(result, containedAttributes);
|
||||
|
||||
+2
-2
@@ -343,7 +343,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
}
|
||||
|
||||
|
||||
private InjectionMetadata findResourceMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
|
||||
private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
|
||||
// Fall back to class name as cache key, for backwards compatibility with custom callers.
|
||||
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
|
||||
// Quick check on the concurrent map first, with minimal locking.
|
||||
@@ -363,7 +363,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
return metadata;
|
||||
}
|
||||
|
||||
private InjectionMetadata buildResourceMetadata(Class<?> clazz) {
|
||||
private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
|
||||
if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
|
||||
return InjectionMetadata.EMPTY;
|
||||
}
|
||||
|
||||
+59
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -16,10 +16,13 @@
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
@@ -30,7 +33,12 @@ import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.type.filter.AbstractTypeHierarchyTraversingFilter;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.AspectJTypeFilter;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.core.type.filter.RegexPatternTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -65,7 +73,7 @@ class ComponentScanAnnotationParser {
|
||||
}
|
||||
|
||||
|
||||
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, String declaringClass) {
|
||||
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
|
||||
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
|
||||
|
||||
@@ -85,17 +93,13 @@ class ComponentScanAnnotationParser {
|
||||
|
||||
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
|
||||
|
||||
for (AnnotationAttributes includeFilterAttributes : componentScan.getAnnotationArray("includeFilters")) {
|
||||
List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(includeFilterAttributes, this.environment,
|
||||
this.resourceLoader, this.registry);
|
||||
for (TypeFilter typeFilter : typeFilters) {
|
||||
for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
|
||||
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
|
||||
scanner.addIncludeFilter(typeFilter);
|
||||
}
|
||||
}
|
||||
for (AnnotationAttributes excludeFilterAttributes : componentScan.getAnnotationArray("excludeFilters")) {
|
||||
List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(excludeFilterAttributes, this.environment,
|
||||
this.resourceLoader, this.registry);
|
||||
for (TypeFilter typeFilter : typeFilters) {
|
||||
for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
|
||||
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
|
||||
scanner.addExcludeFilter(typeFilter);
|
||||
}
|
||||
}
|
||||
@@ -128,4 +132,49 @@ class ComponentScanAnnotationParser {
|
||||
return scanner.doScan(StringUtils.toStringArray(basePackages));
|
||||
}
|
||||
|
||||
private List<TypeFilter> typeFiltersFor(AnnotationAttributes filterAttributes) {
|
||||
List<TypeFilter> typeFilters = new ArrayList<>();
|
||||
FilterType filterType = filterAttributes.getEnum("type");
|
||||
|
||||
for (Class<?> filterClass : filterAttributes.getClassArray("classes")) {
|
||||
switch (filterType) {
|
||||
case ANNOTATION:
|
||||
Assert.isAssignable(Annotation.class, filterClass,
|
||||
"@ComponentScan ANNOTATION type filter requires an annotation type");
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<Annotation> annotationType = (Class<Annotation>) filterClass;
|
||||
typeFilters.add(new AnnotationTypeFilter(annotationType));
|
||||
break;
|
||||
case ASSIGNABLE_TYPE:
|
||||
typeFilters.add(new AssignableTypeFilter(filterClass));
|
||||
break;
|
||||
case CUSTOM:
|
||||
Assert.isAssignable(TypeFilter.class, filterClass,
|
||||
"@ComponentScan CUSTOM type filter requires a TypeFilter implementation");
|
||||
|
||||
TypeFilter filter = ParserStrategyUtils.instantiateClass(filterClass, TypeFilter.class,
|
||||
this.environment, this.resourceLoader, this.registry);
|
||||
typeFilters.add(filter);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Filter type not supported with Class value: " + filterType);
|
||||
}
|
||||
}
|
||||
|
||||
for (String expression : filterAttributes.getStringArray("pattern")) {
|
||||
switch (filterType) {
|
||||
case ASPECTJ:
|
||||
typeFilters.add(new AspectJTypeFilter(expression, this.resourceLoader.getClassLoader()));
|
||||
break;
|
||||
case REGEX:
|
||||
typeFilters.add(new RegexPatternTypeFilter(Pattern.compile(expression)));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Filter type not supported with String pattern: " + filterType);
|
||||
}
|
||||
}
|
||||
|
||||
return typeFilters;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -453,8 +453,8 @@ class ConfigurationClassEnhancer {
|
||||
* instance directly. If a FactoryBean instance is fetched through the container via &-dereferencing,
|
||||
* it will not be proxied. This too is aligned with the way XML configuration works.
|
||||
*/
|
||||
private Object enhanceFactoryBean(Object factoryBean, Class<?> exposedType,
|
||||
ConfigurableBeanFactory beanFactory, String beanName) {
|
||||
private Object enhanceFactoryBean(final Object factoryBean, Class<?> exposedType,
|
||||
final ConfigurableBeanFactory beanFactory, final String beanName) {
|
||||
|
||||
try {
|
||||
Class<?> clazz = factoryBean.getClass();
|
||||
@@ -489,8 +489,8 @@ class ConfigurationClassEnhancer {
|
||||
return createCglibProxyForFactoryBean(factoryBean, beanFactory, beanName);
|
||||
}
|
||||
|
||||
private Object createInterfaceProxyForFactoryBean(Object factoryBean, Class<?> interfaceType,
|
||||
ConfigurableBeanFactory beanFactory, String beanName) {
|
||||
private Object createInterfaceProxyForFactoryBean(final Object factoryBean, Class<?> interfaceType,
|
||||
final ConfigurableBeanFactory beanFactory, final String beanName) {
|
||||
|
||||
return Proxy.newProxyInstance(
|
||||
factoryBean.getClass().getClassLoader(), new Class<?>[] {interfaceType},
|
||||
@@ -502,8 +502,8 @@ class ConfigurationClassEnhancer {
|
||||
});
|
||||
}
|
||||
|
||||
private Object createCglibProxyForFactoryBean(Object factoryBean,
|
||||
ConfigurableBeanFactory beanFactory, String beanName) {
|
||||
private Object createCglibProxyForFactoryBean(final Object factoryBean,
|
||||
final ConfigurableBeanFactory beanFactory, final String beanName) {
|
||||
|
||||
Enhancer enhancer = new Enhancer();
|
||||
enhancer.setSuperclass(factoryBean.getClass());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,11 +47,6 @@ import java.lang.annotation.Target;
|
||||
* or {@link javax.inject.Inject}: In that context, it leads to the creation of a
|
||||
* lazy-resolution proxy for all affected dependencies, as an alternative to using
|
||||
* {@link org.springframework.beans.factory.ObjectFactory} or {@link javax.inject.Provider}.
|
||||
* Please note that such a lazy-resolution proxy will always be injected; if the target
|
||||
* dependency does not exist, you will only be able to find out through an exception on
|
||||
* invocation. As a consequence, such an injection point results in unintuitive behavior
|
||||
* for optional dependencies. For a programmatic equivalent, allowing for lazy references
|
||||
* with more sophistication, consider {@link org.springframework.beans.factory.ObjectProvider}.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.AspectJTypeFilter;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.core.type.filter.RegexPatternTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Collection of utilities for working with {@link ComponentScan @ComponentScan}
|
||||
* {@linkplain ComponentScan.Filter type filters}.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 5.3.13
|
||||
* @see ComponentScan.Filter
|
||||
* @see org.springframework.core.type.filter.TypeFilter
|
||||
*/
|
||||
public abstract class TypeFilterUtils {
|
||||
|
||||
/**
|
||||
* Create {@linkplain TypeFilter type filters} from the supplied
|
||||
* {@link AnnotationAttributes}, such as those sourced from
|
||||
* {@link ComponentScan#includeFilters()} or {@link ComponentScan#excludeFilters()}.
|
||||
* <p>Each {@link TypeFilter} will be instantiated using an appropriate
|
||||
* constructor, with {@code BeanClassLoaderAware}, {@code BeanFactoryAware},
|
||||
* {@code EnvironmentAware}, and {@code ResourceLoaderAware} contracts
|
||||
* invoked if they are implemented by the type filter.
|
||||
* @param filterAttributes {@code AnnotationAttributes} for a
|
||||
* {@link ComponentScan.Filter @Filter} declaration
|
||||
* @param environment the {@code Environment} to make available to filters
|
||||
* @param resourceLoader the {@code ResourceLoader} to make available to filters
|
||||
* @param registry the {@code BeanDefinitionRegistry} to make available to filters
|
||||
* as a {@link org.springframework.beans.factory.BeanFactory} if applicable
|
||||
* @return a list of instantiated and configured type filters
|
||||
* @see TypeFilter
|
||||
* @see AnnotationTypeFilter
|
||||
* @see AssignableTypeFilter
|
||||
* @see AspectJTypeFilter
|
||||
* @see RegexPatternTypeFilter
|
||||
* @see org.springframework.beans.factory.BeanClassLoaderAware
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.context.EnvironmentAware
|
||||
* @see org.springframework.context.ResourceLoaderAware
|
||||
*/
|
||||
public static List<TypeFilter> createTypeFiltersFor(AnnotationAttributes filterAttributes, Environment environment,
|
||||
ResourceLoader resourceLoader, BeanDefinitionRegistry registry) {
|
||||
|
||||
List<TypeFilter> typeFilters = new ArrayList<>();
|
||||
FilterType filterType = filterAttributes.getEnum("type");
|
||||
|
||||
for (Class<?> filterClass : filterAttributes.getClassArray("classes")) {
|
||||
switch (filterType) {
|
||||
case ANNOTATION:
|
||||
Assert.isAssignable(Annotation.class, filterClass,
|
||||
"@ComponentScan ANNOTATION type filter requires an annotation type");
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<Annotation> annotationType = (Class<Annotation>) filterClass;
|
||||
typeFilters.add(new AnnotationTypeFilter(annotationType));
|
||||
break;
|
||||
case ASSIGNABLE_TYPE:
|
||||
typeFilters.add(new AssignableTypeFilter(filterClass));
|
||||
break;
|
||||
case CUSTOM:
|
||||
Assert.isAssignable(TypeFilter.class, filterClass,
|
||||
"@ComponentScan CUSTOM type filter requires a TypeFilter implementation");
|
||||
TypeFilter filter = ParserStrategyUtils.instantiateClass(filterClass, TypeFilter.class,
|
||||
environment, resourceLoader, registry);
|
||||
typeFilters.add(filter);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Filter type not supported with Class value: " + filterType);
|
||||
}
|
||||
}
|
||||
|
||||
for (String expression : filterAttributes.getStringArray("pattern")) {
|
||||
switch (filterType) {
|
||||
case ASPECTJ:
|
||||
typeFilters.add(new AspectJTypeFilter(expression, resourceLoader.getClassLoader()));
|
||||
break;
|
||||
case REGEX:
|
||||
typeFilters.add(new RegexPatternTypeFilter(Pattern.compile(expression)));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Filter type not supported with String pattern: " + filterType);
|
||||
}
|
||||
}
|
||||
|
||||
return typeFilters;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-11
@@ -75,7 +75,7 @@ public abstract class CachedExpressionEvaluator {
|
||||
|
||||
/**
|
||||
* Return the {@link Expression} for the specified SpEL value
|
||||
* <p>{@link #parseExpression(String) Parse the expression} if it hasn't been already.
|
||||
* <p>Parse the expression if it hasn't been already.
|
||||
* @param cache the cache to use
|
||||
* @param elementKey the element on which the expression is defined
|
||||
* @param expression the expression to parse
|
||||
@@ -86,21 +86,12 @@ public abstract class CachedExpressionEvaluator {
|
||||
ExpressionKey expressionKey = createKey(elementKey, expression);
|
||||
Expression expr = cache.get(expressionKey);
|
||||
if (expr == null) {
|
||||
expr = parseExpression(expression);
|
||||
expr = getParser().parseExpression(expression);
|
||||
cache.put(expressionKey, expr);
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the specified {@code expression}.
|
||||
* @param expression the expression to parse
|
||||
* @since 5.3.13
|
||||
*/
|
||||
protected Expression parseExpression(String expression) {
|
||||
return getParser().parseExpression(expression);
|
||||
}
|
||||
|
||||
private ExpressionKey createKey(AnnotatedElementKey elementKey, String expression) {
|
||||
return new ExpressionKey(elementKey, expression);
|
||||
}
|
||||
|
||||
+1
-1
@@ -107,7 +107,7 @@ public final class CandidateComponentsIndexLoader {
|
||||
result.add(properties);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Loaded " + result.size() + " index(es)");
|
||||
logger.debug("Loaded " + result.size() + "] index(es)");
|
||||
}
|
||||
int totalCount = result.stream().mapToInt(Properties::size).sum();
|
||||
return (totalCount > 0 ? new CandidateComponentsIndex(result) : null);
|
||||
|
||||
-10
@@ -1331,16 +1331,6 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
return getBeanFactory().findAnnotationOnBean(beanName, annotationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <A extends Annotation> A findAnnotationOnBean(
|
||||
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
|
||||
assertBeanFactoryActive();
|
||||
return getBeanFactory().findAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of HierarchicalBeanFactory interface
|
||||
|
||||
+14
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author 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,14 +16,11 @@
|
||||
|
||||
package org.springframework.scheduling.annotation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
@@ -31,7 +28,6 @@ import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.function.SingletonSupplier;
|
||||
|
||||
/**
|
||||
* Abstract base {@code Configuration} class providing common structure for enabling
|
||||
@@ -59,7 +55,7 @@ public abstract class AbstractAsyncConfiguration implements ImportAware {
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
this.enableAsync = AnnotationAttributes.fromMap(
|
||||
importMetadata.getAnnotationAttributes(EnableAsync.class.getName()));
|
||||
importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false));
|
||||
if (this.enableAsync == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"@EnableAsync is not present on importing class " + importMetadata.getClassName());
|
||||
@@ -69,27 +65,17 @@ public abstract class AbstractAsyncConfiguration implements ImportAware {
|
||||
/**
|
||||
* Collect any {@link AsyncConfigurer} beans through autowiring.
|
||||
*/
|
||||
@Autowired
|
||||
void setConfigurers(ObjectProvider<AsyncConfigurer> configurers) {
|
||||
Supplier<AsyncConfigurer> configurer = SingletonSupplier.of(() -> {
|
||||
List<AsyncConfigurer> candidates = configurers.stream().collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(candidates)) {
|
||||
return null;
|
||||
}
|
||||
if (candidates.size() > 1) {
|
||||
throw new IllegalStateException("Only one AsyncConfigurer may exist");
|
||||
}
|
||||
return candidates.get(0);
|
||||
});
|
||||
this.executor = adapt(configurer, AsyncConfigurer::getAsyncExecutor);
|
||||
this.exceptionHandler = adapt(configurer, AsyncConfigurer::getAsyncUncaughtExceptionHandler);
|
||||
}
|
||||
|
||||
private <T> Supplier<T> adapt(Supplier<AsyncConfigurer> supplier, Function<AsyncConfigurer, T> provider) {
|
||||
return () -> {
|
||||
AsyncConfigurer configurer = supplier.get();
|
||||
return (configurer != null ? provider.apply(configurer) : null);
|
||||
};
|
||||
@Autowired(required = false)
|
||||
void setConfigurers(Collection<AsyncConfigurer> configurers) {
|
||||
if (CollectionUtils.isEmpty(configurers)) {
|
||||
return;
|
||||
}
|
||||
if (configurers.size() > 1) {
|
||||
throw new IllegalStateException("Only one AsyncConfigurer may exist");
|
||||
}
|
||||
AsyncConfigurer configurer = configurers.iterator().next();
|
||||
this.executor = configurer::getAsyncExecutor;
|
||||
this.exceptionHandler = configurer::getAsyncUncaughtExceptionHandler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -28,6 +28,11 @@ import org.springframework.lang.Nullable;
|
||||
* {@link AsyncUncaughtExceptionHandler} instance used to process exception thrown from
|
||||
* async method with {@code void} return type.
|
||||
*
|
||||
* <p>Consider using {@link AsyncConfigurerSupport} providing default implementations for
|
||||
* both methods if only one element needs to be customized. Furthermore, backward compatibility
|
||||
* of this interface will be insured in case new customization options are introduced
|
||||
* in the future.
|
||||
*
|
||||
* <p>See @{@link EnableAsync} for usage examples.
|
||||
*
|
||||
* @author Chris Beams
|
||||
@@ -35,6 +40,7 @@ import org.springframework.lang.Nullable;
|
||||
* @since 3.1
|
||||
* @see AbstractAsyncConfiguration
|
||||
* @see EnableAsync
|
||||
* @see AsyncConfigurerSupport
|
||||
*/
|
||||
public interface AsyncConfigurer {
|
||||
|
||||
|
||||
+4
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -26,7 +26,9 @@ import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -63,7 +65,7 @@ import org.springframework.lang.Nullable;
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport
|
||||
implements FactoryBean<ExecutorService> {
|
||||
implements FactoryBean<ExecutorService>, InitializingBean, DisposableBean {
|
||||
|
||||
private int corePoolSize = 1;
|
||||
|
||||
@@ -73,8 +75,6 @@ public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport
|
||||
|
||||
private boolean allowCoreThreadTimeOut = false;
|
||||
|
||||
private boolean prestartAllCoreThreads = false;
|
||||
|
||||
private int queueCapacity = Integer.MAX_VALUE;
|
||||
|
||||
private boolean exposeUnconfigurableExecutor = false;
|
||||
@@ -118,16 +118,6 @@ public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport
|
||||
this.allowCoreThreadTimeOut = allowCoreThreadTimeOut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether to start all core threads, causing them to idly wait for work.
|
||||
* <p>Default is "false".
|
||||
* @since 5.3.14
|
||||
* @see java.util.concurrent.ThreadPoolExecutor#prestartAllCoreThreads
|
||||
*/
|
||||
public void setPrestartAllCoreThreads(boolean prestartAllCoreThreads) {
|
||||
this.prestartAllCoreThreads = prestartAllCoreThreads;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the capacity for the ThreadPoolExecutor's BlockingQueue.
|
||||
* Default is {@code Integer.MAX_VALUE}.
|
||||
@@ -163,9 +153,6 @@ public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport
|
||||
if (this.allowCoreThreadTimeOut) {
|
||||
executor.allowCoreThreadTimeOut(true);
|
||||
}
|
||||
if (this.prestartAllCoreThreads) {
|
||||
executor.prestartAllCoreThreads();
|
||||
}
|
||||
|
||||
// Wrap executor with an unconfigurable decorator.
|
||||
this.exposedExecutor = (this.exposeUnconfigurableExecutor ?
|
||||
|
||||
+1
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -94,8 +94,6 @@ public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport
|
||||
|
||||
private boolean allowCoreThreadTimeOut = false;
|
||||
|
||||
private boolean prestartAllCoreThreads = false;
|
||||
|
||||
@Nullable
|
||||
private TaskDecorator taskDecorator;
|
||||
|
||||
@@ -199,16 +197,6 @@ public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport
|
||||
this.allowCoreThreadTimeOut = allowCoreThreadTimeOut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether to start all core threads, causing them to idly wait for work.
|
||||
* <p>Default is "false".
|
||||
* @since 5.3.14
|
||||
* @see java.util.concurrent.ThreadPoolExecutor#prestartAllCoreThreads
|
||||
*/
|
||||
public void setPrestartAllCoreThreads(boolean prestartAllCoreThreads) {
|
||||
this.prestartAllCoreThreads = prestartAllCoreThreads;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a custom {@link TaskDecorator} to be applied to any {@link Runnable}
|
||||
* about to be executed.
|
||||
@@ -268,9 +256,6 @@ public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport
|
||||
if (this.allowCoreThreadTimeOut) {
|
||||
executor.allowCoreThreadTimeOut(true);
|
||||
}
|
||||
if (this.prestartAllCoreThreads) {
|
||||
executor.prestartAllCoreThreads();
|
||||
}
|
||||
|
||||
this.threadPoolExecutor = executor;
|
||||
return executor;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -418,13 +418,11 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register fields that should be allowed for binding. Default is all fields.
|
||||
* Restrict this for example to avoid unwanted modifications by malicious
|
||||
* users when binding HTTP request parameters.
|
||||
* <p>Supports "xxx*", "*xxx", "*xxx*" and "xxx*yyy" matches (with an
|
||||
* arbitrary number of pattern parts), as well as direct equality. More
|
||||
* sophisticated matching can be implemented by overriding the
|
||||
* {@code isAllowed} method.
|
||||
* Register fields that should be allowed for binding. Default is all
|
||||
* fields. Restrict this for example to avoid unwanted modifications
|
||||
* by malicious users when binding HTTP request parameters.
|
||||
* <p>Supports "xxx*", "*xxx" and "*xxx*" patterns. More sophisticated matching
|
||||
* can be implemented by overriding the {@code isAllowed} method.
|
||||
* <p>Alternatively, specify a list of <i>disallowed</i> fields.
|
||||
* @param allowedFields array of field names
|
||||
* @see #setDisallowedFields
|
||||
@@ -444,13 +442,11 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register fields that should <i>not</i> be allowed for binding. Default
|
||||
* is none. Mark fields as disallowed for example to avoid unwanted
|
||||
* modifications by malicious users when binding HTTP request parameters.
|
||||
* <p>Supports "xxx*", "*xxx", "*xxx*" and "xxx*yyy" matches (with an
|
||||
* arbitrary number of pattern parts), as well as direct equality.
|
||||
* More sophisticated matching can be implemented by overriding the
|
||||
* {@code isAllowed} method.
|
||||
* Register fields that should <i>not</i> be allowed for binding. Default is none.
|
||||
* Mark fields as disallowed for example to avoid unwanted modifications
|
||||
* by malicious users when binding HTTP request parameters.
|
||||
* <p>Supports "xxx*", "*xxx" and "*xxx*" patterns. More sophisticated matching
|
||||
* can be implemented by overriding the {@code isAllowed} method.
|
||||
* <p>Alternatively, specify a list of <i>allowed</i> fields.
|
||||
* @param disallowedFields array of field names
|
||||
* @see #setAllowedFields
|
||||
@@ -776,11 +772,10 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
/**
|
||||
* Return if the given field is allowed for binding.
|
||||
* Invoked for each passed-in property value.
|
||||
* <p>The default implementation checks for "xxx*", "*xxx", "*xxx*" and "xxx*yyy"
|
||||
* matches (with an arbitrary number of pattern parts), as well as direct equality,
|
||||
* in the specified lists of allowed fields and disallowed fields. A field matching
|
||||
* a disallowed pattern will not be accepted even if it also happens to match a
|
||||
* pattern in the allowed list.
|
||||
* <p>The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches,
|
||||
* as well as direct equality, in the specified lists of allowed fields and
|
||||
* disallowed fields. A field matching a disallowed pattern will not be accepted
|
||||
* even if it also happens to match a pattern in the allowed list.
|
||||
* <p>Can be overridden in subclasses.
|
||||
* @param field the field to check
|
||||
* @return if the field is allowed
|
||||
|
||||
+4
-34
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -65,10 +65,10 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIOException;
|
||||
|
||||
/**
|
||||
* @since 13.03.2003
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 13.03.2003
|
||||
*/
|
||||
public class ProxyFactoryBeanTests {
|
||||
|
||||
@@ -633,50 +633,20 @@ public class ProxyFactoryBeanTests {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource(FROZEN_CONTEXT, CLASS));
|
||||
|
||||
Advised advised = (Advised) bf.getBean("frozen");
|
||||
Advised advised = (Advised)bf.getBean("frozen");
|
||||
assertThat(advised.isFrozen()).as("The proxy should be frozen").isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetectsInterfaces() {
|
||||
public void testDetectsInterfaces() throws Exception {
|
||||
ProxyFactoryBean fb = new ProxyFactoryBean();
|
||||
fb.setTarget(new TestBean());
|
||||
fb.addAdvice(new DebugInterceptor());
|
||||
fb.setBeanFactory(new DefaultListableBeanFactory());
|
||||
|
||||
ITestBean proxy = (ITestBean) fb.getObject();
|
||||
assertThat(AopUtils.isJdkDynamicProxy(proxy)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithInterceptorNames() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerSingleton("debug", new DebugInterceptor());
|
||||
|
||||
ProxyFactoryBean fb = new ProxyFactoryBean();
|
||||
fb.setTarget(new TestBean());
|
||||
fb.setInterceptorNames("debug");
|
||||
fb.setBeanFactory(bf);
|
||||
|
||||
Advised proxy = (Advised) fb.getObject();
|
||||
assertThat(proxy.getAdvisorCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithLateInterceptorNames() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerSingleton("debug", new DebugInterceptor());
|
||||
|
||||
ProxyFactoryBean fb = new ProxyFactoryBean();
|
||||
fb.setTarget(new TestBean());
|
||||
fb.setBeanFactory(bf);
|
||||
fb.getObject();
|
||||
|
||||
fb.setInterceptorNames("debug");
|
||||
Advised proxy = (Advised) fb.getObject();
|
||||
assertThat(proxy.getAdvisorCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fires only on void methods. Saves list of methods intercepted.
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author 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,7 @@ import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||
@@ -306,7 +306,7 @@ public class CacheReproTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
public static class Spr13081Config implements CachingConfigurer {
|
||||
public static class Spr13081Config extends CachingConfigurerSupport {
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
|
||||
Vendored
+3
-46
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,7 +26,7 @@ import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
@@ -83,19 +83,6 @@ public class EnableCachingIntegrationTests {
|
||||
assertCacheHit(key, value, cache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void barServiceWithCacheableInterfaceCglib() {
|
||||
this.context = new AnnotationConfigApplicationContext(BarConfigCglib.class);
|
||||
BarService service = this.context.getBean(BarService.class);
|
||||
Cache cache = getCache();
|
||||
|
||||
Object key = new Object();
|
||||
assertCacheMiss(key, cache);
|
||||
|
||||
Object value = service.getSimple(key);
|
||||
assertCacheHit(key, value, cache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanConditionOff() {
|
||||
this.context = new AnnotationConfigApplicationContext(BeanConditionConfig.class);
|
||||
@@ -137,7 +124,7 @@ public class EnableCachingIntegrationTests {
|
||||
|
||||
|
||||
@Configuration
|
||||
static class SharedConfig implements CachingConfigurer {
|
||||
static class SharedConfig extends CachingConfigurerSupport {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
@@ -198,36 +185,6 @@ public class EnableCachingIntegrationTests {
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@Import(SharedConfig.class)
|
||||
@EnableCaching(proxyTargetClass = true)
|
||||
static class BarConfigCglib {
|
||||
|
||||
@Bean
|
||||
public BarService barService() {
|
||||
return new BarServiceImpl();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface BarService {
|
||||
|
||||
@Cacheable(cacheNames = "testCache")
|
||||
Object getSimple(Object key);
|
||||
}
|
||||
|
||||
|
||||
static class BarServiceImpl implements BarService {
|
||||
|
||||
private final AtomicLong counter = new AtomicLong();
|
||||
|
||||
@Override
|
||||
public Object getSimple(Object key) {
|
||||
return this.counter.getAndIncrement();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@Import(FooConfig.class)
|
||||
@EnableCaching
|
||||
|
||||
+11
-7
@@ -18,10 +18,11 @@ package org.springframework.cache.config;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.interceptor.CacheErrorHandler;
|
||||
import org.springframework.cache.interceptor.CacheInterceptor;
|
||||
@@ -106,8 +107,11 @@ public class EnableCachingTests extends AbstractCacheAnnotationTests {
|
||||
try {
|
||||
ctx.refresh();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertThat(ex.getMessage().contains("implementations of CachingConfigurer")).isTrue();
|
||||
catch (BeanCreationException ex) {
|
||||
Throwable root = ex.getRootCause();
|
||||
boolean condition = root instanceof IllegalStateException;
|
||||
assertThat(condition).isTrue();
|
||||
assertThat(root.getMessage().contains("implementations of CachingConfigurer")).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +150,7 @@ public class EnableCachingTests extends AbstractCacheAnnotationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class EnableCachingConfig implements CachingConfigurer {
|
||||
static class EnableCachingConfig extends CachingConfigurerSupport {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
@@ -223,7 +227,7 @@ public class EnableCachingTests extends AbstractCacheAnnotationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class MultiCacheManagerConfigurer implements CachingConfigurer {
|
||||
static class MultiCacheManagerConfigurer extends CachingConfigurerSupport {
|
||||
|
||||
@Bean
|
||||
public CacheManager cm1() {
|
||||
@@ -249,7 +253,7 @@ public class EnableCachingTests extends AbstractCacheAnnotationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class EmptyConfigSupportConfig implements CachingConfigurer {
|
||||
static class EmptyConfigSupportConfig extends CachingConfigurerSupport {
|
||||
|
||||
@Bean
|
||||
public CacheManager cm() {
|
||||
@@ -260,7 +264,7 @@ public class EnableCachingTests extends AbstractCacheAnnotationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class FullCachingConfig implements CachingConfigurer {
|
||||
static class FullCachingConfig extends CachingConfigurerSupport {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
|
||||
spring-context/src/test/java/org/springframework/cache/config/ExpressionCachingIntegrationTests.java
Vendored
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -20,7 +20,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
@@ -122,7 +122,7 @@ public class ExpressionCachingIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class SharedConfig implements CachingConfigurer {
|
||||
static class SharedConfig extends CachingConfigurerSupport {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
|
||||
Vendored
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author 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,7 @@ import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.support.SimpleCacheManager;
|
||||
import org.springframework.cache.support.SimpleValueWrapper;
|
||||
@@ -170,7 +170,7 @@ public class CacheErrorHandlerTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class Config implements CachingConfigurer {
|
||||
static class Config extends CachingConfigurerSupport {
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
|
||||
Vendored
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,7 @@ import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
@@ -106,7 +106,7 @@ public class CachePutEvaluationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class Config implements CachingConfigurer {
|
||||
static class Config extends CachingConfigurerSupport {
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,7 +29,7 @@ import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
@@ -149,7 +149,7 @@ public class CacheResolverCustomizationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class Config implements CachingConfigurer {
|
||||
static class Config extends CachingConfigurerSupport {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
|
||||
Vendored
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,7 +26,7 @@ import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
@@ -133,7 +133,7 @@ public class CacheSyncFailureTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class Config implements CachingConfigurer {
|
||||
static class Config extends CachingConfigurerSupport {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -67,17 +67,6 @@ public class MapAccessorTests {
|
||||
assertThat(ex.getValue(sec,mapGetter)).isEqualTo("bar");
|
||||
assertThat(SpelCompiler.compile(ex)).isTrue();
|
||||
assertThat(ex.getValue(sec,mapGetter)).isEqualTo("bar");
|
||||
|
||||
// basic isWritable
|
||||
ex = sep.parseExpression("foo");
|
||||
assertThat(ex.isWritable(sec,testMap)).isTrue();
|
||||
|
||||
// basic write
|
||||
ex = sep.parseExpression("foo2");
|
||||
ex.setValue(sec, testMap, "bar2");
|
||||
assertThat(ex.getValue(sec,testMap)).isEqualTo("bar2");
|
||||
assertThat(SpelCompiler.compile(ex)).isTrue();
|
||||
assertThat(ex.getValue(sec,testMap)).isEqualTo("bar2");
|
||||
}
|
||||
|
||||
public static class MapGetter {
|
||||
|
||||
+23
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -321,6 +321,28 @@ public class FormattingConversionServiceTests {
|
||||
TypeDescriptor.valueOf(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerDefaultValueViaFormatter() {
|
||||
registerDefaultValue(Date.class, new Date());
|
||||
}
|
||||
|
||||
private <T> void registerDefaultValue(Class<T> clazz, final T defaultValue) {
|
||||
formattingService.addFormatterForFieldType(clazz, new Formatter<T>() {
|
||||
@Override
|
||||
public T parse(String text, Locale locale) {
|
||||
return defaultValue;
|
||||
}
|
||||
@Override
|
||||
public String print(T t, Locale locale) {
|
||||
return defaultValue.toString();
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return defaultValue.toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void introspectedFormatter() {
|
||||
formattingService.addFormatter(new NumberStyleFormatter("#,#00.0#"));
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -218,8 +218,8 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
||||
private void assertFutureWithException(Future<Object> result,
|
||||
TestableAsyncUncaughtExceptionHandler exceptionHandler) {
|
||||
assertThatExceptionOfType(ExecutionException.class).isThrownBy(
|
||||
result::get)
|
||||
.withCauseExactlyInstanceOf(UnsupportedOperationException.class);
|
||||
result::get)
|
||||
.withCauseExactlyInstanceOf(UnsupportedOperationException.class);
|
||||
assertThat(exceptionHandler.isCalled()).as("handler should never be called with Future return type").isFalse();
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
||||
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
static class ConfigWithExceptionHandler implements AsyncConfigurer {
|
||||
static class ConfigWithExceptionHandler extends AsyncConfigurerSupport {
|
||||
|
||||
@Bean
|
||||
public ITestBean target() {
|
||||
|
||||
+1
-45
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,12 +16,8 @@
|
||||
|
||||
package org.springframework.scheduling.concurrent;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.RejectedExecutionHandler;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -29,16 +25,10 @@ import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link ThreadPoolExecutorFactoryBean}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
class ThreadPoolExecutorFactoryBeanTests {
|
||||
@@ -54,28 +44,6 @@ class ThreadPoolExecutorFactoryBeanTests {
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void executorWithDefaultSettingsDoesNotPrestartAllCoreThreads() {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.registerBean("taskExecutor", ThreadPoolExecutorFactoryBean.class, TestThreadPoolExecutorFactoryBean::new);
|
||||
context.refresh();
|
||||
ThreadPoolExecutor threadPoolExecutor = context.getBean(ThreadPoolExecutor.class);
|
||||
verify(threadPoolExecutor, never()).prestartAllCoreThreads();
|
||||
}
|
||||
|
||||
@Test
|
||||
void executorWithPrestartAllCoreThreads() {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.registerBean("taskExecutor", ThreadPoolExecutorFactoryBean.class, () -> {
|
||||
TestThreadPoolExecutorFactoryBean factoryBean = new TestThreadPoolExecutorFactoryBean();
|
||||
factoryBean.setPrestartAllCoreThreads(true);
|
||||
return factoryBean;
|
||||
});
|
||||
context.refresh();
|
||||
ThreadPoolExecutor threadPoolExecutor = context.getBean(ThreadPoolExecutor.class);
|
||||
verify(threadPoolExecutor).prestartAllCoreThreads();
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class ExecutorConfig {
|
||||
@@ -84,19 +52,7 @@ class ThreadPoolExecutorFactoryBeanTests {
|
||||
ThreadPoolExecutorFactoryBean executor() {
|
||||
return new ThreadPoolExecutorFactoryBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class TestThreadPoolExecutorFactoryBean extends ThreadPoolExecutorFactoryBean {
|
||||
|
||||
@Override
|
||||
protected ThreadPoolExecutor createExecutor(
|
||||
int corePoolSize, int maxPoolSize, int keepAliveSeconds, BlockingQueue<Runnable> queue,
|
||||
ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
|
||||
|
||||
return mock(ThreadPoolExecutor.class);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ public class ClassReader {
|
||||
this.b = classFileBuffer;
|
||||
// Check the class' major_version. This field is after the magic and minor_version fields, which
|
||||
// use 4 and 2 bytes respectively.
|
||||
if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V19) {
|
||||
if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V18) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unsupported class file major version " + readShort(classFileOffset + 6));
|
||||
}
|
||||
|
||||
@@ -283,7 +283,6 @@ public interface Opcodes {
|
||||
int V16 = 0 << 16 | 60;
|
||||
int V17 = 0 << 16 | 61;
|
||||
int V18 = 0 << 16 | 62;
|
||||
int V19 = 0 << 16 | 63;
|
||||
|
||||
/**
|
||||
* Version flag indicating that the class is using 'preview' features.
|
||||
|
||||
@@ -37,7 +37,7 @@ import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Contextual descriptor about a type to convert from or to.
|
||||
* <p>Capable of representing arrays and generic collection types.
|
||||
* Capable of representing arrays and generic collection types.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Andy Clement
|
||||
@@ -345,9 +345,9 @@ public class TypeDescriptor implements Serializable {
|
||||
* from the provided collection or array element.
|
||||
* <p>Narrows the {@link #getElementTypeDescriptor() elementType} property to the class
|
||||
* of the provided collection or array element. For example, if this describes a
|
||||
* {@code java.util.List<java.lang.Number>} and the element argument is a
|
||||
* {@code java.util.List<java.lang.Number<} and the element argument is an
|
||||
* {@code java.lang.Integer}, the returned TypeDescriptor will be {@code java.lang.Integer}.
|
||||
* If this describes a {@code java.util.List<?>} and the element argument is a
|
||||
* If this describes a {@code java.util.List<?>} and the element argument is an
|
||||
* {@code java.lang.Integer}, the returned TypeDescriptor will be {@code java.lang.Integer}
|
||||
* as well.
|
||||
* <p>Annotation and nested type context will be preserved in the narrowed
|
||||
@@ -388,9 +388,9 @@ public class TypeDescriptor implements Serializable {
|
||||
* from the provided map key.
|
||||
* <p>Narrows the {@link #getMapKeyTypeDescriptor() mapKeyType} property
|
||||
* to the class of the provided map key. For example, if this describes a
|
||||
* {@code java.util.Map<java.lang.Number, java.lang.String>} and the key
|
||||
* {@code java.util.Map<java.lang.Number, java.lang.String<} and the key
|
||||
* argument is a {@code java.lang.Integer}, the returned TypeDescriptor will be
|
||||
* {@code java.lang.Integer}. If this describes a {@code java.util.Map<?, ?>}
|
||||
* {@code java.lang.Integer}. If this describes a {@code java.util.Map<?, ?>}
|
||||
* and the key argument is a {@code java.lang.Integer}, the returned
|
||||
* TypeDescriptor will be {@code java.lang.Integer} as well.
|
||||
* <p>Annotation and nested type context will be preserved in the narrowed
|
||||
@@ -425,9 +425,9 @@ public class TypeDescriptor implements Serializable {
|
||||
* from the provided map value.
|
||||
* <p>Narrows the {@link #getMapValueTypeDescriptor() mapValueType} property
|
||||
* to the class of the provided map value. For example, if this describes a
|
||||
* {@code java.util.Map<java.lang.String, java.lang.Number>} and the value
|
||||
* {@code java.util.Map<java.lang.String, java.lang.Number<} and the value
|
||||
* argument is a {@code java.lang.Integer}, the returned TypeDescriptor will be
|
||||
* {@code java.lang.Integer}. If this describes a {@code java.util.Map<?, ?>}
|
||||
* {@code java.lang.Integer}. If this describes a {@code java.util.Map<?, ?>}
|
||||
* and the value argument is a {@code java.lang.Integer}, the returned
|
||||
* TypeDescriptor will be {@code java.lang.Integer} as well.
|
||||
* <p>Annotation and nested type context will be preserved in the narrowed
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -462,9 +462,9 @@ public class DefaultDataBuffer implements DataBuffer {
|
||||
|
||||
private void checkIndex(int index, int length) {
|
||||
assertIndex(index >= 0, "index %d must be >= 0", index);
|
||||
assertIndex(length >= 0, "length %d must be >= 0", length);
|
||||
assertIndex(length >= 0, "length %d must be >= 0", index);
|
||||
assertIndex(index <= this.capacity, "index %d must be <= %d", index, this.capacity);
|
||||
assertIndex(length <= this.capacity, "length %d must be <= %d", length, this.capacity);
|
||||
assertIndex(length <= this.capacity, "length %d must be <= %d", index, this.capacity);
|
||||
}
|
||||
|
||||
private void assertIndex(boolean expression, String format, Object... args) {
|
||||
|
||||
@@ -17,12 +17,10 @@
|
||||
package org.springframework.core.log;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Utility methods for formatting and logging messages.
|
||||
@@ -37,15 +35,9 @@ import org.springframework.util.ObjectUtils;
|
||||
*/
|
||||
public abstract class LogFormatUtils {
|
||||
|
||||
private static final Pattern NEWLINE_PATTERN = Pattern.compile("[\n\r]");
|
||||
|
||||
private static final Pattern CONTROL_CHARACTER_PATTERN = Pattern.compile("\\p{Cc}");
|
||||
|
||||
|
||||
/**
|
||||
* Convenience variant of {@link #formatValue(Object, int, boolean)} that
|
||||
* limits the length of a log message to 100 characters and also replaces
|
||||
* newline and control characters if {@code limitLength} is set to "true".
|
||||
* Variant of {@link #formatValue(Object, int, boolean)} and a convenience
|
||||
* method that truncates at 100 characters when {@code limitLength} is set.
|
||||
* @param value the value to format
|
||||
* @param limitLength whether to truncate the value at a length of 100
|
||||
* @return the formatted value
|
||||
@@ -60,29 +52,25 @@ public abstract class LogFormatUtils {
|
||||
* compacting it into a single line when {@code replaceNewLines} is set.
|
||||
* @param value the value to be formatted
|
||||
* @param maxLength the max length, after which to truncate, or -1 for unlimited
|
||||
* @param replaceNewlinesAndControlCharacters whether to replace newline and
|
||||
* control characters with placeholders
|
||||
* @param replaceNewlines whether to replace newline characters with placeholders
|
||||
* @return the formatted value
|
||||
*/
|
||||
public static String formatValue(
|
||||
@Nullable Object value, int maxLength, boolean replaceNewlinesAndControlCharacters) {
|
||||
|
||||
public static String formatValue(@Nullable Object value, int maxLength, boolean replaceNewlines) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
String result;
|
||||
try {
|
||||
result = ObjectUtils.nullSafeToString(value);
|
||||
result = value.toString();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
result = ObjectUtils.nullSafeToString(ex);
|
||||
result = ex.toString();
|
||||
}
|
||||
if (maxLength != -1) {
|
||||
result = (result.length() > maxLength ? result.substring(0, maxLength) + " (truncated)..." : result);
|
||||
}
|
||||
if (replaceNewlinesAndControlCharacters) {
|
||||
result = NEWLINE_PATTERN.matcher(result).replaceAll("<EOL>");
|
||||
result = CONTROL_CHARACTER_PATTERN.matcher(result).replaceAll("?");
|
||||
if (replaceNewlines) {
|
||||
result = result.replace("\n", "<LF>").replace("\r", "<CR>");
|
||||
}
|
||||
if (value instanceof CharSequence) {
|
||||
result = "\"" + result + "\"";
|
||||
|
||||
+1
-1
@@ -162,7 +162,7 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
|
||||
throw new IllegalStateException("Failed to introspect annotated methods on " + getIntrospectedClass(), ex);
|
||||
}
|
||||
}
|
||||
return (annotatedMethods != null ? annotatedMethods : Collections.emptySet());
|
||||
return annotatedMethods != null ? annotatedMethods : Collections.emptySet();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+5
-6
@@ -127,11 +127,6 @@ final class SimpleAnnotationMetadata implements AnnotationMetadata {
|
||||
return this.memberClassNames.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MergedAnnotations getAnnotations() {
|
||||
return this.annotations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAnnotationTypes() {
|
||||
Set<String> annotationTypes = this.annotationTypes;
|
||||
@@ -154,9 +149,13 @@ final class SimpleAnnotationMetadata implements AnnotationMetadata {
|
||||
annotatedMethods.add(annotatedMethod);
|
||||
}
|
||||
}
|
||||
return (annotatedMethods != null ? annotatedMethods : Collections.emptySet());
|
||||
return annotatedMethods != null ? annotatedMethods : Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MergedAnnotations getAnnotations() {
|
||||
return this.annotations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -99,7 +99,8 @@ final class SimpleAnnotationMetadataReadingVisitor extends ClassVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(String name, @Nullable String outerName, String innerName, int access) {
|
||||
public void visitInnerClass(String name, @Nullable String outerName, String innerName,
|
||||
int access) {
|
||||
if (outerName != null) {
|
||||
String className = toClassName(name);
|
||||
String outerClassName = toClassName(outerName);
|
||||
|
||||
@@ -733,10 +733,6 @@ public class AntPathMatcher implements PathMatcher {
|
||||
}
|
||||
for (int i = 1; i <= matcher.groupCount(); i++) {
|
||||
String name = this.variableNames.get(i - 1);
|
||||
if (name.startsWith("*")) {
|
||||
throw new IllegalArgumentException("Capturing patterns (" + name + ") are not " +
|
||||
"supported by the AntPathMatcher. Use the PathPatternParser instead.");
|
||||
}
|
||||
String value = matcher.group(i);
|
||||
uriTemplateVariables.put(name, value);
|
||||
}
|
||||
|
||||
@@ -637,20 +637,14 @@ public class MimeType implements Comparable<MimeType>, Serializable {
|
||||
else if (mimeType2.isWildcardType() && !mimeType1.isWildcardType()) { // audio/* > */*
|
||||
return -1;
|
||||
}
|
||||
else if (!mimeType1.getType().equals(mimeType2.getType())) { // audio/basic == text/html
|
||||
return 0;
|
||||
}
|
||||
else { // mediaType1.getType().equals(mediaType2.getType())
|
||||
else {
|
||||
if (mimeType1.isWildcardSubtype() && !mimeType2.isWildcardSubtype()) { // audio/* < audio/basic
|
||||
return 1;
|
||||
}
|
||||
else if (mimeType2.isWildcardSubtype() && !mimeType1.isWildcardSubtype()) { // audio/basic > audio/*
|
||||
return -1;
|
||||
}
|
||||
else if (!mimeType1.getSubtype().equals(mimeType2.getSubtype())) { // audio/basic == audio/wave
|
||||
return 0;
|
||||
}
|
||||
else { // mediaType2.getSubtype().equals(mediaType2.getSubtype())
|
||||
else {
|
||||
return compareParameters(mimeType1, mimeType2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1159,20 +1159,6 @@ class ResolvableTypeTests {
|
||||
assertThatResolvableType(complex4).isNotAssignableFrom(complex3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void identifyTypeVariable() throws Exception {
|
||||
Method method = ClassArguments.class.getMethod("typedArgumentFirst", Class.class, Class.class, Class.class);
|
||||
ResolvableType returnType = ResolvableType.forMethodReturnType(method, ClassArguments.class);
|
||||
|
||||
ResolvableType arg0 = ResolvableType.forMethodParameter(method, 0, ClassArguments.class);
|
||||
ResolvableType arg1 = ResolvableType.forMethodParameter(method, 1, ClassArguments.class);
|
||||
ResolvableType arg2 = ResolvableType.forMethodParameter(method, 2, ClassArguments.class);
|
||||
|
||||
assertThat(returnType.getType().equals(arg0.as(Class.class).getGeneric(0).getType())).isTrue();
|
||||
assertThat(returnType.getType().equals(arg1.as(Class.class).getGeneric(0).getType())).isFalse();
|
||||
assertThat(returnType.getType().equals(arg2.as(Class.class).getGeneric(0).getType())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void hashCodeAndEquals() throws Exception {
|
||||
ResolvableType forClass = ResolvableType.forClass(List.class);
|
||||
@@ -1441,10 +1427,6 @@ class ResolvableTypeTests {
|
||||
}
|
||||
|
||||
|
||||
interface TypedMethods extends Methods<String> {
|
||||
}
|
||||
|
||||
|
||||
static class AssignmentBase<O, C, S> {
|
||||
|
||||
public O o;
|
||||
@@ -1497,9 +1479,7 @@ class ResolvableTypeTests {
|
||||
}
|
||||
|
||||
|
||||
interface ClassArguments {
|
||||
|
||||
<T> T typedArgumentFirst(Class<T> arg0, Class<?> arg1, Class<Object> arg2);
|
||||
interface TypedMethods extends Methods<String> {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -44,7 +44,7 @@ public interface TypeConverter {
|
||||
* Convert (or coerce) a value from one type to another, for example from a
|
||||
* {@code boolean} to a {@code String}.
|
||||
* <p>The {@link TypeDescriptor} parameters enable support for typed collections:
|
||||
* A caller may prefer a {@code List<Integer>}, for example, rather than
|
||||
* A caller may prefer a {@code List<Integer>}, for example, rather than
|
||||
* simply any {@code List}.
|
||||
* @param value the value to be converted
|
||||
* @param sourceType a type descriptor that supplies extra information about the
|
||||
|
||||
+23
-42
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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,7 +20,6 @@ import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
@@ -39,7 +38,6 @@ import org.springframework.util.MethodInvoker;
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class ReflectionHelper {
|
||||
@@ -283,41 +281,25 @@ public abstract class ReflectionHelper {
|
||||
arguments[i] = converter.convertValue(argument, TypeDescriptor.forObject(argument), targetType);
|
||||
conversionOccurred |= (argument != arguments[i]);
|
||||
}
|
||||
|
||||
MethodParameter methodParam = MethodParameter.forExecutable(executable, varargsPosition);
|
||||
|
||||
// If the target is varargs and there is just one more argument, then convert it here.
|
||||
if (varargsPosition == arguments.length - 1) {
|
||||
Object argument = arguments[varargsPosition];
|
||||
// If the target is varargs and there is just one more argument
|
||||
// then convert it here
|
||||
TypeDescriptor targetType = new TypeDescriptor(methodParam);
|
||||
Object argument = arguments[varargsPosition];
|
||||
TypeDescriptor sourceType = TypeDescriptor.forObject(argument);
|
||||
if (argument == null) {
|
||||
// Perform the equivalent of GenericConversionService.convertNullSource() for a single argument.
|
||||
if (targetType.getElementTypeDescriptor().getObjectType() == Optional.class) {
|
||||
arguments[varargsPosition] = Optional.empty();
|
||||
conversionOccurred = true;
|
||||
}
|
||||
}
|
||||
// If the argument type is equal to the varargs element type, there is no need to
|
||||
// convert it or wrap it in an array. For example, using StringToArrayConverter to
|
||||
// convert a String containing a comma would result in the String being split and
|
||||
// repackaged in an array when it should be used as-is.
|
||||
else if (!sourceType.equals(targetType.getElementTypeDescriptor())) {
|
||||
arguments[varargsPosition] = converter.convertValue(argument, sourceType, targetType);
|
||||
}
|
||||
// Possible outcomes of the above if-else block:
|
||||
// 1) the input argument was null, and nothing was done.
|
||||
// 2) the input argument was null; the varargs element type is Optional; and the argument was converted to Optional.empty().
|
||||
// 3) the input argument was correct type but not wrapped in an array, and nothing was done.
|
||||
// 4) the input argument was already compatible (i.e., array of valid type), and nothing was done.
|
||||
// 5) the input argument was the wrong type and got converted and wrapped in an array.
|
||||
arguments[varargsPosition] = converter.convertValue(argument, sourceType, targetType);
|
||||
// Three outcomes of that previous line:
|
||||
// 1) the input argument was already compatible (ie. array of valid type) and nothing was done
|
||||
// 2) the input argument was correct type but not in an array so it was made into an array
|
||||
// 3) the input argument was the wrong type and got converted and put into an array
|
||||
if (argument != arguments[varargsPosition] &&
|
||||
!isFirstEntryInArray(argument, arguments[varargsPosition])) {
|
||||
conversionOccurred = true; // case 5
|
||||
conversionOccurred = true; // case 3
|
||||
}
|
||||
}
|
||||
// Otherwise, convert remaining arguments to the varargs element type.
|
||||
else {
|
||||
// Convert remaining arguments to the varargs element type
|
||||
TypeDescriptor targetType = new TypeDescriptor(methodParam).getElementTypeDescriptor();
|
||||
Assert.state(targetType != null, "No element type");
|
||||
for (int i = varargsPosition; i < arguments.length; i++) {
|
||||
@@ -350,8 +332,8 @@ public abstract class ReflectionHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Package up the arguments so that they correctly match what is expected in requiredParameterTypes.
|
||||
* <p>For example, if requiredParameterTypes is {@code (int, String[])} because the second parameter
|
||||
* Package up the arguments so that they correctly match what is expected in parameterTypes.
|
||||
* For example, if parameterTypes is {@code (int, String[])} because the second parameter
|
||||
* was declared {@code String...}, then if arguments is {@code [1,"a","b"]} then it must be
|
||||
* repackaged as {@code [1,new String[]{"a","b"}]} in order to match the expected types.
|
||||
* @param requiredParameterTypes the types of the parameters for the invocation
|
||||
@@ -368,24 +350,23 @@ public abstract class ReflectionHelper {
|
||||
requiredParameterTypes[parameterCount - 1] !=
|
||||
(args[argumentCount - 1] != null ? args[argumentCount - 1].getClass() : null)) {
|
||||
|
||||
// Create an array for the leading arguments plus the varargs array argument.
|
||||
int arraySize = 0; // zero size array if nothing to pass as the varargs parameter
|
||||
if (argumentCount >= parameterCount) {
|
||||
arraySize = argumentCount - (parameterCount - 1);
|
||||
}
|
||||
|
||||
// Create an array for the varargs arguments
|
||||
Object[] newArgs = new Object[parameterCount];
|
||||
// Copy all leading arguments to the new array, omitting the varargs array argument.
|
||||
System.arraycopy(args, 0, newArgs, 0, newArgs.length - 1);
|
||||
|
||||
// Now sort out the final argument, which is the varargs one. Before entering this method,
|
||||
// the arguments should have been converted to the box form of the required type.
|
||||
int varargsArraySize = 0; // zero size array if nothing to pass as the varargs parameter
|
||||
if (argumentCount >= parameterCount) {
|
||||
varargsArraySize = argumentCount - (parameterCount - 1);
|
||||
}
|
||||
Class<?> componentType = requiredParameterTypes[parameterCount - 1].getComponentType();
|
||||
Object varargsArray = Array.newInstance(componentType, varargsArraySize);
|
||||
for (int i = 0; i < varargsArraySize; i++) {
|
||||
Array.set(varargsArray, i, args[parameterCount - 1 + i]);
|
||||
Object repackagedArgs = Array.newInstance(componentType, arraySize);
|
||||
for (int i = 0; i < arraySize; i++) {
|
||||
Array.set(repackagedArgs, i, args[parameterCount - 1 + i]);
|
||||
}
|
||||
// Finally, add the varargs array to the new arguments array.
|
||||
newArgs[newArgs.length - 1] = varargsArray;
|
||||
newArgs[newArgs.length - 1] = repackagedArgs;
|
||||
return newArgs;
|
||||
}
|
||||
return args;
|
||||
|
||||
+17
-69
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,7 +46,6 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
|
||||
@@ -234,77 +233,26 @@ public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
|
||||
@Test
|
||||
public void testVarargsInvocation01() {
|
||||
// Calling 'public String aVarargsMethod(String... strings)'
|
||||
evaluate("aVarargsMethod('a','b','c')", "[a, b, c]", String.class);
|
||||
evaluate("aVarargsMethod('a')", "[a]", String.class);
|
||||
evaluate("aVarargsMethod()", "[]", String.class);
|
||||
evaluate("aVarargsMethod(1,2,3)", "[1, 2, 3]", String.class); // all need converting to strings
|
||||
evaluate("aVarargsMethod(1)", "[1]", String.class); // needs string conversion
|
||||
evaluate("aVarargsMethod(1,'a',3.0d)", "[1, a, 3.0]", String.class); // first and last need conversion
|
||||
evaluate("aVarargsMethod(new String[]{'a','b','c'})", "[a, b, c]", String.class);
|
||||
evaluate("aVarargsMethod(new String[]{})", "[]", String.class);
|
||||
evaluate("aVarargsMethod(null)", "[null]", String.class);
|
||||
evaluate("aVarargsMethod(null,'a')", "[null, a]", String.class);
|
||||
evaluate("aVarargsMethod('a',null,'b')", "[a, null, b]", String.class);
|
||||
// Calling 'public int aVarargsMethod(String... strings)'
|
||||
//evaluate("aVarargsMethod('a','b','c')", 3, Integer.class);
|
||||
//evaluate("aVarargsMethod('a')", 1, Integer.class);
|
||||
evaluate("aVarargsMethod()", 0, Integer.class);
|
||||
evaluate("aVarargsMethod(1,2,3)", 3, Integer.class); // all need converting to strings
|
||||
evaluate("aVarargsMethod(1)", 1, Integer.class); // needs string conversion
|
||||
evaluate("aVarargsMethod(1,'a',3.0d)", 3, Integer.class); // first and last need conversion
|
||||
// evaluate("aVarargsMethod(new String[]{'a','b','c'})", 3, Integer.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVarargsInvocation02() {
|
||||
// Calling 'public String aVarargsMethod2(int i, String... strings)'
|
||||
evaluate("aVarargsMethod2(5,'a','b','c')", "5-[a, b, c]", String.class);
|
||||
evaluate("aVarargsMethod2(2,'a')", "2-[a]", String.class);
|
||||
evaluate("aVarargsMethod2(4)", "4-[]", String.class);
|
||||
evaluate("aVarargsMethod2(8,2,3)", "8-[2, 3]", String.class);
|
||||
evaluate("aVarargsMethod2(2,'a',3.0d)", "2-[a, 3.0]", String.class);
|
||||
evaluate("aVarargsMethod2(8,new String[]{'a','b','c'})", "8-[a, b, c]", String.class);
|
||||
evaluate("aVarargsMethod2(8,new String[]{})", "8-[]", String.class);
|
||||
evaluate("aVarargsMethod2(8,null)", "8-[null]", String.class);
|
||||
evaluate("aVarargsMethod2(8,null,'a')", "8-[null, a]", String.class);
|
||||
evaluate("aVarargsMethod2(8,'a',null,'b')", "8-[a, null, b]", String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVarargsInvocation03() {
|
||||
// Calling 'public int aVarargsMethod3(String str1, String... strings)' - returns all strings concatenated with "-"
|
||||
|
||||
// No conversion necessary
|
||||
evaluate("aVarargsMethod3('x')", "x", String.class);
|
||||
evaluate("aVarargsMethod3('x', 'a')", "x-a", String.class);
|
||||
evaluate("aVarargsMethod3('x', 'a', 'b', 'c')", "x-a-b-c", String.class);
|
||||
|
||||
// Conversion necessary
|
||||
evaluate("aVarargsMethod3(9)", "9", String.class);
|
||||
evaluate("aVarargsMethod3(8,2,3)", "8-2-3", String.class);
|
||||
evaluate("aVarargsMethod3('2','a',3.0d)", "2-a-3.0", String.class);
|
||||
evaluate("aVarargsMethod3('8',new String[]{'a','b','c'})", "8-a-b-c", String.class);
|
||||
|
||||
// Individual string contains a comma with multiple varargs arguments
|
||||
evaluate("aVarargsMethod3('foo', ',', 'baz')", "foo-,-baz", String.class);
|
||||
evaluate("aVarargsMethod3('foo', 'bar', ',baz')", "foo-bar-,baz", String.class);
|
||||
evaluate("aVarargsMethod3('foo', 'bar,', 'baz')", "foo-bar,-baz", String.class);
|
||||
|
||||
// Individual string contains a comma with single varargs argument.
|
||||
// Reproduces https://github.com/spring-projects/spring-framework/issues/27582
|
||||
evaluate("aVarargsMethod3('foo', ',')", "foo-,", String.class);
|
||||
evaluate("aVarargsMethod3('foo', ',bar')", "foo-,bar", String.class);
|
||||
evaluate("aVarargsMethod3('foo', 'bar,')", "foo-bar,", String.class);
|
||||
evaluate("aVarargsMethod3('foo', 'bar,baz')", "foo-bar,baz", String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVarargsOptionalInvocation() {
|
||||
// Calling 'public String optionalVarargsMethod(Optional<String>... values)'
|
||||
evaluate("optionalVarargsMethod()", "[]", String.class);
|
||||
evaluate("optionalVarargsMethod(new String[0])", "[]", String.class);
|
||||
evaluate("optionalVarargsMethod('a')", "[Optional[a]]", String.class);
|
||||
evaluate("optionalVarargsMethod('a','b','c')", "[Optional[a], Optional[b], Optional[c]]", String.class);
|
||||
evaluate("optionalVarargsMethod(9)", "[Optional[9]]", String.class);
|
||||
evaluate("optionalVarargsMethod(2,3)", "[Optional[2], Optional[3]]", String.class);
|
||||
evaluate("optionalVarargsMethod('a',3.0d)", "[Optional[a], Optional[3.0]]", String.class);
|
||||
evaluate("optionalVarargsMethod(new String[]{'a','b','c'})", "[Optional[a], Optional[b], Optional[c]]", String.class);
|
||||
evaluate("optionalVarargsMethod(null)", "[Optional.empty]", String.class);
|
||||
evaluate("optionalVarargsMethod(null,'a')", "[Optional.empty, Optional[a]]", String.class);
|
||||
evaluate("optionalVarargsMethod('a',null,'b')", "[Optional[a], Optional.empty, Optional[b]]", String.class);
|
||||
// Calling 'public int aVarargsMethod2(int i, String... strings)' - returns int+length_of_strings
|
||||
evaluate("aVarargsMethod2(5,'a','b','c')", 8, Integer.class);
|
||||
evaluate("aVarargsMethod2(2,'a')", 3, Integer.class);
|
||||
evaluate("aVarargsMethod2(4)", 4, Integer.class);
|
||||
evaluate("aVarargsMethod2(8,2,3)", 10, Integer.class);
|
||||
evaluate("aVarargsMethod2(9)", 9, Integer.class);
|
||||
evaluate("aVarargsMethod2(2,'a',3.0d)", 4, Integer.class);
|
||||
// evaluate("aVarargsMethod2(8,new String[]{'a','b','c'})", 11, Integer.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+22
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.expression.spel;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
@@ -52,10 +51,10 @@ public class TestScenarioCreator {
|
||||
TestScenarioCreator.class.getDeclaredMethod("reverseInt", Integer.TYPE, Integer.TYPE, Integer.TYPE));
|
||||
testContext.registerFunction("reverseString",
|
||||
TestScenarioCreator.class.getDeclaredMethod("reverseString", String.class));
|
||||
testContext.registerFunction("varargsFunction",
|
||||
TestScenarioCreator.class.getDeclaredMethod("varargsFunction", String[].class));
|
||||
testContext.registerFunction("varargsFunction2",
|
||||
TestScenarioCreator.class.getDeclaredMethod("varargsFunction2", Integer.TYPE, String[].class));
|
||||
testContext.registerFunction("varargsFunctionReverseStringsAndMerge",
|
||||
TestScenarioCreator.class.getDeclaredMethod("varargsFunctionReverseStringsAndMerge", String[].class));
|
||||
testContext.registerFunction("varargsFunctionReverseStringsAndMerge2",
|
||||
TestScenarioCreator.class.getDeclaredMethod("varargsFunctionReverseStringsAndMerge2", Integer.TYPE, String[].class));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
@@ -109,12 +108,25 @@ public class TestScenarioCreator {
|
||||
return backwards.toString();
|
||||
}
|
||||
|
||||
public static String varargsFunction(String... strings) {
|
||||
return Arrays.toString(strings);
|
||||
public static String varargsFunctionReverseStringsAndMerge(String... strings) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (strings != null) {
|
||||
for (int i = strings.length - 1; i >= 0; i--) {
|
||||
sb.append(strings[i]);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String varargsFunction2(int i, String... strings) {
|
||||
return String.valueOf(i) + "-" + Arrays.toString(strings);
|
||||
public static String varargsFunctionReverseStringsAndMerge2(int j, String... strings) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(j);
|
||||
if (strings != null) {
|
||||
for (int i = strings.length - 1; i >= 0; i--) {
|
||||
sb.append(strings[i]);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-29
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author 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 static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
* Tests the evaluation of expressions that access variables and functions (lambda/java).
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public class VariableAndFunctionTests extends AbstractExpressionTests {
|
||||
|
||||
@@ -59,33 +58,16 @@ public class VariableAndFunctionTests extends AbstractExpressionTests {
|
||||
|
||||
@Test
|
||||
public void testCallVarargsFunction() {
|
||||
evaluate("#varargsFunction()", "[]", String.class);
|
||||
evaluate("#varargsFunction(new String[0])", "[]", String.class);
|
||||
evaluate("#varargsFunction('a')", "[a]", String.class);
|
||||
evaluate("#varargsFunction('a','b','c')", "[a, b, c]", String.class);
|
||||
// Conversion from int to String
|
||||
evaluate("#varargsFunction(25)", "[25]", String.class);
|
||||
evaluate("#varargsFunction('b',25)", "[b, 25]", String.class);
|
||||
// Strings that contain a comma
|
||||
evaluate("#varargsFunction('a,b')", "[a,b]", String.class);
|
||||
evaluate("#varargsFunction('a', 'x,y', 'd')", "[a, x,y, d]", String.class);
|
||||
// null values
|
||||
evaluate("#varargsFunction(null)", "[null]", String.class);
|
||||
evaluate("#varargsFunction('a',null,'b')", "[a, null, b]", String.class);
|
||||
|
||||
evaluate("#varargsFunction2(9)", "9-[]", String.class);
|
||||
evaluate("#varargsFunction2(9, new String[0])", "9-[]", String.class);
|
||||
evaluate("#varargsFunction2(9,'a')", "9-[a]", String.class);
|
||||
evaluate("#varargsFunction2(9,'a','b','c')", "9-[a, b, c]", String.class);
|
||||
// Conversion from int to String
|
||||
evaluate("#varargsFunction2(9,25)", "9-[25]", String.class);
|
||||
evaluate("#varargsFunction2(9,'b',25)", "9-[b, 25]", String.class);
|
||||
// Strings that contain a comma:
|
||||
evaluate("#varargsFunction2(9, 'a,b')", "9-[a,b]", String.class);
|
||||
evaluate("#varargsFunction2(9, 'a', 'x,y', 'd')", "9-[a, x,y, d]", String.class);
|
||||
// null values
|
||||
evaluate("#varargsFunction2(9,null)", "9-[null]", String.class);
|
||||
evaluate("#varargsFunction2(9,'a',null,'b')", "9-[a, null, b]", String.class);
|
||||
evaluate("#varargsFunctionReverseStringsAndMerge('a','b','c')", "cba", String.class);
|
||||
evaluate("#varargsFunctionReverseStringsAndMerge('a')", "a", String.class);
|
||||
evaluate("#varargsFunctionReverseStringsAndMerge()", "", String.class);
|
||||
evaluate("#varargsFunctionReverseStringsAndMerge('b',25)", "25b", String.class);
|
||||
evaluate("#varargsFunctionReverseStringsAndMerge(25)", "25", String.class);
|
||||
evaluate("#varargsFunctionReverseStringsAndMerge2(1,'a','b','c')", "1cba", String.class);
|
||||
evaluate("#varargsFunctionReverseStringsAndMerge2(2,'a')", "2a", String.class);
|
||||
evaluate("#varargsFunctionReverseStringsAndMerge2(3)", "3", String.class);
|
||||
evaluate("#varargsFunctionReverseStringsAndMerge2(4,'b',25)", "425b", String.class);
|
||||
evaluate("#varargsFunctionReverseStringsAndMerge2(5,25)", "525", String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+10
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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,20 +17,17 @@
|
||||
package org.springframework.expression.spel.testresources;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
///CLOVER:OFF
|
||||
@SuppressWarnings("unused")
|
||||
public class Inventor {
|
||||
|
||||
private String name;
|
||||
public String _name;
|
||||
public String _name_;
|
||||
@@ -193,27 +190,20 @@ public class Inventor {
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
public String aVarargsMethod(String... strings) {
|
||||
return Arrays.toString(strings);
|
||||
public int aVarargsMethod(String... strings) {
|
||||
if (strings == null)
|
||||
return 0;
|
||||
return strings.length;
|
||||
}
|
||||
|
||||
public String aVarargsMethod2(int i, String... strings) {
|
||||
return String.valueOf(i) + "-" + Arrays.toString(strings);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public String optionalVarargsMethod(Optional<String>... values) {
|
||||
return Arrays.toString(values);
|
||||
}
|
||||
|
||||
public String aVarargsMethod3(String str1, String... strings) {
|
||||
if (ObjectUtils.isEmpty(strings)) {
|
||||
return str1;
|
||||
}
|
||||
return str1 + "-" + String.join("-", strings);
|
||||
public int aVarargsMethod2(int i, String... strings) {
|
||||
if (strings == null)
|
||||
return i;
|
||||
return strings.length + i;
|
||||
}
|
||||
|
||||
public Inventor(String... strings) {
|
||||
|
||||
}
|
||||
|
||||
public boolean getSomeProperty() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author 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,21 +22,22 @@ import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.jdbc.support.KeyHolder;
|
||||
import org.springframework.jdbc.support.rowset.SqlRowSet;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Interface specifying a basic set of JDBC operations.
|
||||
*
|
||||
* <p>Implemented by {@link JdbcTemplate}. Not often used directly, but a useful
|
||||
* Implemented by {@link JdbcTemplate}. Not often used directly, but a useful
|
||||
* option to enhance testability, as it can easily be mocked or stubbed.
|
||||
*
|
||||
* <p>Alternatively, the standard JDBC infrastructure can be mocked.
|
||||
* However, mocking this interface constitutes significantly less work.
|
||||
* As an alternative to a mock objects approach to testing data access code,
|
||||
* consider the powerful integration testing support provided via the <em>Spring
|
||||
* TestContext Framework</em>, in the {@code spring-test} artifact.
|
||||
* consider the powerful integration testing support provided in the
|
||||
* {@code org.springframework.test} package, shipped in
|
||||
* {@code spring-test.jar}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
@@ -159,8 +160,8 @@ public interface JdbcOperations {
|
||||
* @param rowMapper a callback that will map one object per row
|
||||
* @return the single mapped object (may be {@code null} if the given
|
||||
* {@link RowMapper} returned {@code} null)
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* @throws IncorrectResultSizeDataAccessException if the query does not
|
||||
* return exactly one row
|
||||
* @throws DataAccessException if there is any problem executing the query
|
||||
* @see #queryForObject(String, RowMapper, Object...)
|
||||
*/
|
||||
@@ -179,10 +180,8 @@ public interface JdbcOperations {
|
||||
* @param sql the SQL query to execute
|
||||
* @param requiredType the type that the result object is expected to match
|
||||
* @return the result object of the required type, or {@code null} in case of SQL NULL
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* @throws org.springframework.jdbc.IncorrectResultSetColumnCountException
|
||||
* if the query does not return a row containing a single column
|
||||
* @throws IncorrectResultSizeDataAccessException if the query does not return
|
||||
* exactly one row, or does not return exactly one column in that row
|
||||
* @throws DataAccessException if there is any problem executing the query
|
||||
* @see #queryForObject(String, Class, Object...)
|
||||
*/
|
||||
@@ -199,8 +198,8 @@ public interface JdbcOperations {
|
||||
* mapped to a Map (one entry for each column, using the column name as the key).
|
||||
* @param sql the SQL query to execute
|
||||
* @return the result Map (one entry per column, with column name as key)
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* @throws IncorrectResultSizeDataAccessException if the query does not
|
||||
* return exactly one row
|
||||
* @throws DataAccessException if there is any problem executing the query
|
||||
* @see #queryForMap(String, Object...)
|
||||
* @see ColumnMapRowMapper
|
||||
@@ -604,8 +603,8 @@ public interface JdbcOperations {
|
||||
* @param rowMapper a callback that will map one object per row
|
||||
* @return the single mapped object (may be {@code null} if the given
|
||||
* {@link RowMapper} returned {@code} null)
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* @throws IncorrectResultSizeDataAccessException if the query does not
|
||||
* return exactly one row
|
||||
* @throws DataAccessException if the query fails
|
||||
*/
|
||||
@Nullable
|
||||
@@ -624,8 +623,8 @@ public interface JdbcOperations {
|
||||
* @param rowMapper a callback that will map one object per row
|
||||
* @return the single mapped object (may be {@code null} if the given
|
||||
* {@link RowMapper} returned {@code} null)
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* @throws IncorrectResultSizeDataAccessException if the query does not
|
||||
* return exactly one row
|
||||
* @throws DataAccessException if the query fails
|
||||
* @deprecated as of 5.3, in favor of {@link #queryForObject(String, RowMapper, Object...)}
|
||||
*/
|
||||
@@ -645,8 +644,8 @@ public interface JdbcOperations {
|
||||
* only the argument value but also the SQL type and optionally the scale
|
||||
* @return the single mapped object (may be {@code null} if the given
|
||||
* {@link RowMapper} returned {@code} null)
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* @throws IncorrectResultSizeDataAccessException if the query does not
|
||||
* return exactly one row
|
||||
* @throws DataAccessException if the query fails
|
||||
* @since 3.0.1
|
||||
*/
|
||||
@@ -664,10 +663,8 @@ public interface JdbcOperations {
|
||||
* (constants from {@code java.sql.Types})
|
||||
* @param requiredType the type that the result object is expected to match
|
||||
* @return the result object of the required type, or {@code null} in case of SQL NULL
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* @throws org.springframework.jdbc.IncorrectResultSetColumnCountException
|
||||
* if the query does not return a row containing a single column
|
||||
* @throws IncorrectResultSizeDataAccessException if the query does not return
|
||||
* exactly one row, or does not return exactly one column in that row
|
||||
* @throws DataAccessException if the query fails
|
||||
* @see #queryForObject(String, Class)
|
||||
* @see java.sql.Types
|
||||
@@ -688,10 +685,8 @@ public interface JdbcOperations {
|
||||
* only the argument value but also the SQL type and optionally the scale
|
||||
* @param requiredType the type that the result object is expected to match
|
||||
* @return the result object of the required type, or {@code null} in case of SQL NULL
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* @throws org.springframework.jdbc.IncorrectResultSetColumnCountException
|
||||
* if the query does not return a row containing a single column
|
||||
* @throws IncorrectResultSizeDataAccessException if the query does not return
|
||||
* exactly one row, or does not return exactly one column in that row
|
||||
* @throws DataAccessException if the query fails
|
||||
* @see #queryForObject(String, Class)
|
||||
* @deprecated as of 5.3, in favor of {@link #queryForObject(String, Class, Object...)}
|
||||
@@ -712,10 +707,8 @@ public interface JdbcOperations {
|
||||
* may also contain {@link SqlParameterValue} objects which indicate not
|
||||
* only the argument value but also the SQL type and optionally the scale
|
||||
* @return the result object of the required type, or {@code null} in case of SQL NULL
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* @throws org.springframework.jdbc.IncorrectResultSetColumnCountException
|
||||
* if the query does not return a row containing a single column
|
||||
* @throws IncorrectResultSizeDataAccessException if the query does not return
|
||||
* exactly one row, or does not return exactly one column in that row
|
||||
* @throws DataAccessException if the query fails
|
||||
* @since 3.0.1
|
||||
* @see #queryForObject(String, Class)
|
||||
@@ -733,8 +726,8 @@ public interface JdbcOperations {
|
||||
* @param argTypes the SQL types of the arguments
|
||||
* (constants from {@code java.sql.Types})
|
||||
* @return the result Map (one entry per column, with column name as key)
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* @throws IncorrectResultSizeDataAccessException if the query does not
|
||||
* return exactly one row
|
||||
* @throws DataAccessException if the query fails
|
||||
* @see #queryForMap(String)
|
||||
* @see ColumnMapRowMapper
|
||||
@@ -757,8 +750,8 @@ public interface JdbcOperations {
|
||||
* only the argument value but also the SQL type and optionally the scale
|
||||
* @return the result Map (one entry for each column, using the
|
||||
* column name as the key)
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* @throws IncorrectResultSizeDataAccessException if the query does not
|
||||
* return exactly one row
|
||||
* @throws DataAccessException if the query fails
|
||||
* @see #queryForMap(String)
|
||||
* @see ColumnMapRowMapper
|
||||
|
||||
+9
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -268,7 +268,8 @@ public interface NamedParameterJdbcOperations {
|
||||
* @return the single mapped object (may be {@code null} if the given
|
||||
* {@link RowMapper} returned {@code} null)
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* if the query does not return exactly one row, or does not return exactly
|
||||
* one column in that row
|
||||
* @throws DataAccessException if the query fails
|
||||
*/
|
||||
@Nullable
|
||||
@@ -286,7 +287,8 @@ public interface NamedParameterJdbcOperations {
|
||||
* @return the single mapped object (may be {@code null} if the given
|
||||
* {@link RowMapper} returned {@code} null)
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* if the query does not return exactly one row, or does not return exactly
|
||||
* one column in that row
|
||||
* @throws DataAccessException if the query fails
|
||||
*/
|
||||
@Nullable
|
||||
@@ -303,12 +305,10 @@ public interface NamedParameterJdbcOperations {
|
||||
* @param requiredType the type that the result object is expected to match
|
||||
* @return the result object of the required type, or {@code null} in case of SQL NULL
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* @throws org.springframework.jdbc.IncorrectResultSetColumnCountException
|
||||
* if the query does not return a row containing a single column
|
||||
* if the query does not return exactly one row, or does not return exactly
|
||||
* one column in that row
|
||||
* @throws DataAccessException if the query fails
|
||||
* @see org.springframework.jdbc.core.JdbcTemplate#queryForObject(String, Class)
|
||||
* @see org.springframework.jdbc.core.SingleColumnRowMapper
|
||||
*/
|
||||
@Nullable
|
||||
<T> T queryForObject(String sql, SqlParameterSource paramSource, Class<T> requiredType)
|
||||
@@ -325,9 +325,8 @@ public interface NamedParameterJdbcOperations {
|
||||
* @param requiredType the type that the result object is expected to match
|
||||
* @return the result object of the required type, or {@code null} in case of SQL NULL
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row
|
||||
* @throws org.springframework.jdbc.IncorrectResultSetColumnCountException
|
||||
* if the query does not return a row containing a single column
|
||||
* if the query does not return exactly one row, or does not return exactly
|
||||
* one column in that row
|
||||
* @throws DataAccessException if the query fails
|
||||
* @see org.springframework.jdbc.core.JdbcTemplate#queryForObject(String, Class)
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -87,8 +87,6 @@ public abstract class StoredProcedure extends SqlCall {
|
||||
* they appear in the database's stored procedure parameter list.</b>
|
||||
* <p>Names are purely used to help mapping.
|
||||
* @param param the parameter object
|
||||
* @throws InvalidDataAccessApiUsageException if the parameter has no name, or if the
|
||||
* operation is already compiled, and hence cannot be configured further
|
||||
*/
|
||||
@Override
|
||||
public void declareParameter(SqlParameter param) throws InvalidDataAccessApiUsageException {
|
||||
|
||||
-161
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.jdbc.datasource.lookup;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
|
||||
|
||||
/**
|
||||
* Tests for {@link AbstractRoutingDataSource}.
|
||||
*
|
||||
* @author Kazuki Shimizu
|
||||
*/
|
||||
class AbstractRoutingDataSourceTests {
|
||||
|
||||
@Test
|
||||
void setTargetDataSources() {
|
||||
final ThreadLocal<String> lookupKey = new ThreadLocal<>();
|
||||
AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
|
||||
@Override
|
||||
protected Object determineCurrentLookupKey() {
|
||||
return lookupKey.get();
|
||||
}
|
||||
};
|
||||
DataSource ds1 = new StubDataSource();
|
||||
DataSource ds2 = new StubDataSource();
|
||||
|
||||
MapDataSourceLookup dataSourceLookup = new MapDataSourceLookup();
|
||||
dataSourceLookup.addDataSource("dataSource2", ds2);
|
||||
routingDataSource.setDataSourceLookup(dataSourceLookup);
|
||||
|
||||
Map<Object, Object> targetDataSources = new HashMap<>();
|
||||
targetDataSources.put("ds1", ds1);
|
||||
targetDataSources.put("ds2", "dataSource2");
|
||||
routingDataSource.setTargetDataSources(targetDataSources);
|
||||
|
||||
routingDataSource.afterPropertiesSet();
|
||||
lookupKey.set("ds1");
|
||||
assertThat(routingDataSource.determineTargetDataSource()).isSameAs(ds1);
|
||||
lookupKey.set("ds2");
|
||||
assertThat(routingDataSource.determineTargetDataSource()).isSameAs(ds2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void targetDataSourcesIsNull() {
|
||||
AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
|
||||
@Override
|
||||
protected Object determineCurrentLookupKey() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
assertThatIllegalArgumentException().isThrownBy(routingDataSource::afterPropertiesSet)
|
||||
.withMessage("Property 'targetDataSources' is required");
|
||||
}
|
||||
|
||||
@Test
|
||||
void dataSourceIsUnSupportedType() {
|
||||
AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
|
||||
@Override
|
||||
protected Object determineCurrentLookupKey() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
Map<Object, Object> targetDataSources = new HashMap<>();
|
||||
targetDataSources.put("ds1", 1);
|
||||
routingDataSource.setTargetDataSources(targetDataSources);
|
||||
assertThatIllegalArgumentException().isThrownBy(routingDataSource::afterPropertiesSet)
|
||||
.withMessage("Illegal data source value - only [javax.sql.DataSource] and String supported: 1");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void setDefaultTargetDataSource() {
|
||||
final ThreadLocal<String> lookupKey = new ThreadLocal<>();
|
||||
AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
|
||||
@Override
|
||||
protected Object determineCurrentLookupKey() {
|
||||
return lookupKey.get();
|
||||
}
|
||||
};
|
||||
DataSource ds = new StubDataSource();
|
||||
routingDataSource.setTargetDataSources(new HashMap<>());
|
||||
routingDataSource.setDefaultTargetDataSource(ds);
|
||||
routingDataSource.afterPropertiesSet();
|
||||
lookupKey.set("foo");
|
||||
assertThat(routingDataSource.determineTargetDataSource()).isSameAs(ds);
|
||||
}
|
||||
|
||||
@Test
|
||||
void setDefaultTargetDataSourceFallbackIsFalse() {
|
||||
final ThreadLocal<String> lookupKey = new ThreadLocal<>();
|
||||
AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
|
||||
@Override
|
||||
protected Object determineCurrentLookupKey() {
|
||||
return lookupKey.get();
|
||||
}
|
||||
};
|
||||
DataSource ds = new StubDataSource();
|
||||
routingDataSource.setTargetDataSources(new HashMap<>());
|
||||
routingDataSource.setDefaultTargetDataSource(ds);
|
||||
routingDataSource.setLenientFallback(false);
|
||||
routingDataSource.afterPropertiesSet();
|
||||
lookupKey.set("foo");
|
||||
assertThatIllegalStateException().isThrownBy(routingDataSource::determineTargetDataSource)
|
||||
.withMessage("Cannot determine target DataSource for lookup key [foo]");
|
||||
}
|
||||
|
||||
@Test
|
||||
void setDefaultTargetDataSourceLookupKeyIsNullWhenFallbackIsFalse() {
|
||||
final ThreadLocal<String> lookupKey = new ThreadLocal<>();
|
||||
AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
|
||||
@Override
|
||||
protected Object determineCurrentLookupKey() {
|
||||
return lookupKey.get();
|
||||
}
|
||||
};
|
||||
DataSource ds = new StubDataSource();
|
||||
routingDataSource.setTargetDataSources(new HashMap<>());
|
||||
routingDataSource.setDefaultTargetDataSource(ds);
|
||||
routingDataSource.setLenientFallback(false);
|
||||
routingDataSource.afterPropertiesSet();
|
||||
lookupKey.set(null);
|
||||
assertThat(routingDataSource.determineTargetDataSource()).isSameAs(ds);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notInitialized() {
|
||||
AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
|
||||
@Override
|
||||
protected Object determineCurrentLookupKey() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
assertThatIllegalArgumentException().isThrownBy(routingDataSource::determineTargetDataSource)
|
||||
.withMessage("DataSource router not initialized");
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -230,10 +230,10 @@ public abstract class ExtendedEntityManagerCreator {
|
||||
|
||||
if (emIfc != null) {
|
||||
interfaces = cachedEntityManagerInterfaces.computeIfAbsent(emIfc, key -> {
|
||||
if (EntityManagerProxy.class.equals(key)) {
|
||||
return new Class<?>[] {key};
|
||||
}
|
||||
return new Class<?>[] {key, EntityManagerProxy.class};
|
||||
Set<Class<?>> ifcs = new LinkedHashSet<>(4);
|
||||
ifcs.add(key);
|
||||
ifcs.add(EntityManagerProxy.class);
|
||||
return ClassUtils.toClassArray(ifcs);
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -373,7 +373,7 @@ public class PersistenceAnnotationBeanPostProcessor
|
||||
}
|
||||
|
||||
|
||||
private InjectionMetadata findPersistenceMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
|
||||
private InjectionMetadata findPersistenceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
|
||||
// Fall back to class name as cache key, for backwards compatibility with custom callers.
|
||||
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
|
||||
// Quick check on the concurrent map first, with minimal locking.
|
||||
@@ -393,7 +393,7 @@ public class PersistenceAnnotationBeanPostProcessor
|
||||
return metadata;
|
||||
}
|
||||
|
||||
private InjectionMetadata buildPersistenceMetadata(Class<?> clazz) {
|
||||
private InjectionMetadata buildPersistenceMetadata(final Class<?> clazz) {
|
||||
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(PersistenceContext.class, PersistenceUnit.class))) {
|
||||
return InjectionMetadata.EMPTY;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ import com.thoughtworks.xstream.io.xml.DomReader;
|
||||
import com.thoughtworks.xstream.io.xml.DomWriter;
|
||||
import com.thoughtworks.xstream.io.xml.QNameMap;
|
||||
import com.thoughtworks.xstream.io.xml.SaxWriter;
|
||||
import com.thoughtworks.xstream.io.xml.StaxDriver;
|
||||
import com.thoughtworks.xstream.io.xml.StaxReader;
|
||||
import com.thoughtworks.xstream.io.xml.StaxWriter;
|
||||
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
|
||||
@@ -697,14 +696,7 @@ public class XStreamMarshaller extends AbstractMarshaller implements BeanClassLo
|
||||
@Override
|
||||
protected void marshalXmlStreamWriter(Object graph, XMLStreamWriter streamWriter) throws XmlMappingException {
|
||||
try {
|
||||
StaxWriter writer;
|
||||
if (this.streamDriver instanceof StaxDriver) {
|
||||
writer = ((StaxDriver) this.streamDriver).createStaxWriter(streamWriter);
|
||||
}
|
||||
else {
|
||||
writer = new StaxWriter(new QNameMap(), streamWriter, this.nameCoder);
|
||||
}
|
||||
doMarshal(graph, writer, null);
|
||||
doMarshal(graph, new StaxWriter(new QNameMap(), streamWriter, this.nameCoder), null);
|
||||
}
|
||||
catch (XMLStreamException ex) {
|
||||
throw convertXStreamException(ex, true);
|
||||
|
||||
@@ -43,8 +43,6 @@ import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
|
||||
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
|
||||
import com.thoughtworks.xstream.io.json.JsonWriter;
|
||||
import com.thoughtworks.xstream.io.xml.QNameMap;
|
||||
import com.thoughtworks.xstream.io.xml.StaxDriver;
|
||||
import com.thoughtworks.xstream.security.AnyTypePermission;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -178,23 +176,6 @@ class XStreamMarshallerTests {
|
||||
assertThat(XmlContent.from(writer)).isSimilarTo(EXPECTED_STRING);
|
||||
}
|
||||
|
||||
@Test
|
||||
void marshalStaxResultXMLStreamWriterDefaultNamespace() throws Exception {
|
||||
QNameMap map = new QNameMap();
|
||||
map.setDefaultNamespace("https://example.com");
|
||||
map.setDefaultPrefix("spr");
|
||||
StaxDriver driver = new StaxDriver(map);
|
||||
marshaller.setStreamDriver(driver);
|
||||
|
||||
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
|
||||
StringWriter writer = new StringWriter();
|
||||
XMLStreamWriter streamWriter = outputFactory.createXMLStreamWriter(writer);
|
||||
Result result = StaxUtils.createStaxResult(streamWriter);
|
||||
marshaller.marshal(flight, result);
|
||||
assertThat(XmlContent.from(writer)).isSimilarTo(
|
||||
"<spr:flight xmlns:spr=\"https://example.com\"><spr:flightNumber>42</spr:flightNumber></spr:flight>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void marshalStaxResultXMLEventWriter() throws Exception {
|
||||
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
|
||||
|
||||
@@ -60,6 +60,9 @@ dependencies {
|
||||
testImplementation("org.hibernate:hibernate-core")
|
||||
testImplementation("org.hibernate:hibernate-validator")
|
||||
testImplementation("javax.validation:validation-api")
|
||||
testImplementation("org.junit.platform:junit-platform-runner") {
|
||||
exclude group: "junit", module: "junit"
|
||||
}
|
||||
testImplementation("org.junit.platform:junit-platform-testkit")
|
||||
testImplementation("com.fasterxml.jackson.core:jackson-databind")
|
||||
testImplementation("com.thoughtworks.xstream:xstream")
|
||||
|
||||
+8
-8
@@ -112,8 +112,8 @@ public class MergedContextConfiguration implements Serializable {
|
||||
* @param activeProfiles the merged active bean definition profiles
|
||||
* @param contextLoader the resolved {@code ContextLoader}
|
||||
*/
|
||||
public MergedContextConfiguration(Class<?> testClass, @Nullable String[] locations, @Nullable Class<?>[] classes,
|
||||
@Nullable String[] activeProfiles, @Nullable ContextLoader contextLoader) {
|
||||
public MergedContextConfiguration(Class<?> testClass, String[] locations, Class<?>[] classes,
|
||||
String[] activeProfiles, ContextLoader contextLoader) {
|
||||
|
||||
this(testClass, locations, classes, null, activeProfiles, contextLoader);
|
||||
}
|
||||
@@ -128,9 +128,9 @@ public class MergedContextConfiguration implements Serializable {
|
||||
* @param activeProfiles the merged active bean definition profiles
|
||||
* @param contextLoader the resolved {@code ContextLoader}
|
||||
*/
|
||||
public MergedContextConfiguration(Class<?> testClass, @Nullable String[] locations, @Nullable Class<?>[] classes,
|
||||
public MergedContextConfiguration(Class<?> testClass, String[] locations, Class<?>[] classes,
|
||||
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
|
||||
@Nullable String[] activeProfiles, @Nullable ContextLoader contextLoader) {
|
||||
String[] activeProfiles, ContextLoader contextLoader) {
|
||||
|
||||
this(testClass, locations, classes, contextInitializerClasses, activeProfiles, contextLoader, null, null);
|
||||
}
|
||||
@@ -149,9 +149,9 @@ public class MergedContextConfiguration implements Serializable {
|
||||
* @param parent the parent configuration or {@code null} if there is no parent
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public MergedContextConfiguration(Class<?> testClass, @Nullable String[] locations, @Nullable Class<?>[] classes,
|
||||
public MergedContextConfiguration(Class<?> testClass, String[] locations, Class<?>[] classes,
|
||||
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
|
||||
@Nullable String[] activeProfiles, @Nullable ContextLoader contextLoader,
|
||||
String[] activeProfiles, ContextLoader contextLoader,
|
||||
@Nullable CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
|
||||
@Nullable MergedContextConfiguration parent) {
|
||||
|
||||
@@ -197,7 +197,7 @@ public class MergedContextConfiguration implements Serializable {
|
||||
public MergedContextConfiguration(Class<?> testClass, @Nullable String[] locations, @Nullable Class<?>[] classes,
|
||||
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
|
||||
@Nullable String[] activeProfiles, @Nullable String[] propertySourceLocations,
|
||||
@Nullable String[] propertySourceProperties, @Nullable ContextLoader contextLoader,
|
||||
@Nullable String[] propertySourceProperties, ContextLoader contextLoader,
|
||||
@Nullable CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
|
||||
@Nullable MergedContextConfiguration parent) {
|
||||
|
||||
@@ -235,7 +235,7 @@ public class MergedContextConfiguration implements Serializable {
|
||||
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
|
||||
@Nullable String[] activeProfiles, @Nullable String[] propertySourceLocations,
|
||||
@Nullable String[] propertySourceProperties, @Nullable Set<ContextCustomizer> contextCustomizers,
|
||||
@Nullable ContextLoader contextLoader, @Nullable CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
|
||||
ContextLoader contextLoader, @Nullable CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
|
||||
@Nullable MergedContextConfiguration parent) {
|
||||
|
||||
this.testClass = testClass;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -193,7 +193,7 @@ public class ContentRequestMatchers {
|
||||
* <li>{@link Resource} - content from a file
|
||||
* <li>{@code byte[]} - other raw content
|
||||
* </ul>
|
||||
* <p><strong>Note:</strong> This method uses the Apache Commons FileUpload
|
||||
* <p><strong>Note:</strong> This method uses the Apache Commons File Upload
|
||||
* library to parse the multipart data and it must be on the test classpath.
|
||||
* @param expectedMap the expected multipart values
|
||||
* @since 5.3
|
||||
|
||||
+3
-4
@@ -17,7 +17,6 @@
|
||||
package org.springframework.test.web.reactive.server;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
@@ -211,10 +210,10 @@ public class CookieAssertions {
|
||||
private ResponseCookie getCookie(String name) {
|
||||
ResponseCookie cookie = this.exchangeResult.getResponseCookies().getFirst(name);
|
||||
if (cookie == null) {
|
||||
this.exchangeResult.assertWithDiagnostics(() ->
|
||||
AssertionErrors.fail("No cookie with name '" + name + "'"));
|
||||
String message = "No cookie with name '" + name + "'";
|
||||
this.exchangeResult.assertWithDiagnostics(() -> AssertionErrors.fail(message));
|
||||
}
|
||||
return Objects.requireNonNull(cookie);
|
||||
return cookie;
|
||||
}
|
||||
|
||||
private String getMessage(String cookie) {
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,6 @@ package org.springframework.test.web.reactive.server;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
@@ -74,7 +73,7 @@ public class HeaderAssertions {
|
||||
String actual = getHeaders().getFirst(headerName);
|
||||
this.exchangeResult.assertWithDiagnostics(() ->
|
||||
assertTrue("Response does not contain header '" + headerName + "'", actual != null));
|
||||
return assertHeader(headerName, value, Long.parseLong(Objects.requireNonNull(actual)));
|
||||
return assertHeader(headerName, value, Long.parseLong(actual));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,7 +115,7 @@ public class HeaderAssertions {
|
||||
/**
|
||||
* Match all values of the response header with the given regex
|
||||
* patterns which are applied to the values of the header in the
|
||||
* same order. Note that the number of patterns must match the
|
||||
* same order. Note that the number of pattenrs must match the
|
||||
* number of actual values.
|
||||
* @param name the header name
|
||||
* @param patterns one or more regex patterns, one per expected value
|
||||
@@ -204,7 +203,7 @@ public class HeaderAssertions {
|
||||
this.exchangeResult.assertWithDiagnostics(() ->
|
||||
AssertionErrors.fail(getMessage(name) + " not found"));
|
||||
}
|
||||
return Objects.requireNonNull(values);
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -314,15 +314,6 @@ class StubWebApplicationContext implements WebApplicationContext {
|
||||
return this.beanFactory.findAnnotationOnBean(beanName, annotationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <A extends Annotation> A findAnnotationOnBean(
|
||||
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
|
||||
return this.beanFactory.findAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of HierarchicalBeanFactory interface
|
||||
|
||||
+7
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author 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,7 +31,7 @@ import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.AsyncConfigurer;
|
||||
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -73,17 +73,13 @@ public class EventPublishingTestExecutionListenerIntegrationTests {
|
||||
private static final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
|
||||
private final TestContextManager testContextManager = new TestContextManager(ExampleTestCase.class);
|
||||
|
||||
private final TestContext testContext = testContextManager.getTestContext();
|
||||
|
||||
// Note that the following invocation of getApplicationContext() forces eager
|
||||
// loading of the test's ApplicationContext which consequently results in the
|
||||
// publication of all test execution events. Otherwise, TestContext#publishEvent
|
||||
// would never fire any events for ExampleTestCase.
|
||||
private final TestExecutionListener listener = testContext.getApplicationContext().getBean(TestExecutionListener.class);
|
||||
|
||||
private final Object testInstance = new ExampleTestCase();
|
||||
|
||||
private final Method traceableTestMethod = ReflectionUtils.findMethod(ExampleTestCase.class, "traceableTest");
|
||||
|
||||
|
||||
@@ -131,8 +127,8 @@ public class EventPublishingTestExecutionListenerIntegrationTests {
|
||||
public void beforeTestMethodAnnotationWithFailingEventListener() throws Exception {
|
||||
Method method = ReflectionUtils.findMethod(ExampleTestCase.class, "testWithFailingEventListener");
|
||||
assertThatExceptionOfType(RuntimeException.class).isThrownBy(() ->
|
||||
testContextManager.beforeTestMethod(testInstance, method))
|
||||
.withMessageContaining("Boom!");
|
||||
testContextManager.beforeTestMethod(testInstance, method))
|
||||
.withMessageContaining("Boom!");
|
||||
verify(listener, only()).beforeTestMethod(testContext);
|
||||
}
|
||||
|
||||
@@ -153,7 +149,7 @@ public class EventPublishingTestExecutionListenerIntegrationTests {
|
||||
|
||||
verify(listener, only()).beforeTestMethod(testContext);
|
||||
assertThat(TrackingAsyncUncaughtExceptionHandler.asyncException.getMessage())
|
||||
.startsWith("Asynchronous exception for test method [" + methodName + "] in thread [" + THREAD_NAME_PREFIX);
|
||||
.startsWith("Asynchronous exception for test method [" + methodName + "] in thread [" + THREAD_NAME_PREFIX);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -215,7 +211,7 @@ public class EventPublishingTestExecutionListenerIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableAsync(proxyTargetClass = true)
|
||||
static class TestEventListenerConfiguration implements AsyncConfigurer {
|
||||
static class TestEventListenerConfiguration extends AsyncConfigurerSupport {
|
||||
|
||||
@Override
|
||||
public Executor getAsyncExecutor() {
|
||||
@@ -310,7 +306,7 @@ public class EventPublishingTestExecutionListenerIntegrationTests {
|
||||
public void beforeTestMethodWithAsyncFailure(BeforeTestMethodEvent event) throws Exception {
|
||||
this.listener.beforeTestMethod(event.getSource());
|
||||
throw new RuntimeException(String.format("Asynchronous exception for test method [%s] in thread [%s]",
|
||||
event.getTestContext().getTestMethod().getName(), Thread.currentThread().getName()));
|
||||
event.getTestContext().getTestMethod().getName(), Thread.currentThread().getName()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,6 +38,7 @@ import org.springframework.util.Assert;
|
||||
* PersistenceExceptionTranslator} interface, which are subsequently asked to translate
|
||||
* candidate exceptions.
|
||||
*
|
||||
|
||||
* <p>All of Spring's applicable resource factories (e.g.
|
||||
* {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean})
|
||||
* implement the {@code PersistenceExceptionTranslator} interface out of the box.
|
||||
@@ -46,11 +47,6 @@ import org.springframework.util.Assert;
|
||||
* with the {@code @Repository} annotation, along with defining this post-processor
|
||||
* as a bean in the application context.
|
||||
*
|
||||
* <p>As of 5.3, {@code PersistenceExceptionTranslator} beans will be sorted according
|
||||
* to Spring's dependency ordering rules: see {@link org.springframework.core.Ordered}
|
||||
* and {@link org.springframework.core.annotation.Order}. Note that such beans will
|
||||
* get retrieved from any scope, not just singleton scope, as of this 5.3 revision.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -57,7 +57,7 @@ public abstract class AbstractTransactionManagementConfiguration implements Impo
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
this.enableTx = AnnotationAttributes.fromMap(
|
||||
importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName()));
|
||||
importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
|
||||
if (this.enableTx == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -163,7 +163,7 @@ public abstract class AbstractFallbackTransactionAttributeSource
|
||||
*/
|
||||
@Nullable
|
||||
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
|
||||
// Don't allow non-public methods, as configured.
|
||||
// Don't allow no-public methods as required.
|
||||
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,12 +23,12 @@ import org.springframework.util.ObjectUtils;
|
||||
/**
|
||||
* Represents an HTTP request or response entity, consisting of headers and body.
|
||||
*
|
||||
* <p>Often used in combination with the {@link org.springframework.web.client.RestTemplate},
|
||||
* <p>Typically used in combination with the {@link org.springframework.web.client.RestTemplate},
|
||||
* like so:
|
||||
* <pre class="code">
|
||||
* HttpHeaders headers = new HttpHeaders();
|
||||
* headers.setContentType(MediaType.TEXT_PLAIN);
|
||||
* HttpEntity<String> entity = new HttpEntity<>("Hello World", headers);
|
||||
* HttpEntity<String> entity = new HttpEntity<String>(helloWorld, headers);
|
||||
* URI location = template.postForLocation("https://example.com", entity);
|
||||
* </pre>
|
||||
* or
|
||||
@@ -39,11 +39,11 @@ import org.springframework.util.ObjectUtils;
|
||||
* </pre>
|
||||
* Can also be used in Spring MVC, as a return value from a @Controller method:
|
||||
* <pre class="code">
|
||||
* @GetMapping("/handle")
|
||||
* @RequestMapping("/handle")
|
||||
* public HttpEntity<String> handle() {
|
||||
* HttpHeaders responseHeaders = new HttpHeaders();
|
||||
* responseHeaders.set("MyResponseHeader", "MyValue");
|
||||
* return new HttpEntity<>("Hello World", responseHeaders);
|
||||
* return new HttpEntity<String>("Hello World", responseHeaders);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user