mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
192 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ed9cc54fe | |||
| 4173ceefa5 | |||
| 586235e9e4 | |||
| 4f81ab7e14 | |||
| 7281d44178 | |||
| f965c2f5af | |||
| cf5bbce3f8 | |||
| a80e36fd9f | |||
| 840ae05942 | |||
| b5928977d1 | |||
| 5cb950db3b | |||
| 4b7890315f | |||
| f81b1de2c0 | |||
| d9c98801bc | |||
| 70a2219fac | |||
| 083dd0e19d | |||
| e6553939b2 | |||
| 008d011d37 | |||
| 16ab43d957 | |||
| 6c5129b829 | |||
| e25e6a68cf | |||
| bb96bd4f48 | |||
| 370bf184af | |||
| cbcd8fdeba | |||
| 9bb534e74c | |||
| ec915bfd5d | |||
| 5c04c96d0e | |||
| 7d39fbea16 | |||
| 4ad7deda4c | |||
| 4ec02a7e53 | |||
| 2785ef0887 | |||
| b22e670668 | |||
| 436e9d8cdc | |||
| f474595dee | |||
| 42f60fe490 | |||
| ce76a9b5de | |||
| 6d26b962a9 | |||
| a4cc16051c | |||
| c8b49346b1 | |||
| 34b9ca310d | |||
| ea7b0103c5 | |||
| e3175a2dc9 | |||
| 91316dc11b | |||
| ac8d1df3ab | |||
| f023df703a | |||
| 9ab7cde00e | |||
| fad9b509ab | |||
| 5ddbefecea | |||
| a4bba6aff2 | |||
| 906583c40a | |||
| 3689b3fdd5 | |||
| 4a5bac97b5 | |||
| 45a270b71f | |||
| ef013f7158 | |||
| 818d18aa09 | |||
| 4715ad242e | |||
| e51f660286 | |||
| 9f71c98871 | |||
| dbb09334f3 | |||
| 5953d99d1c | |||
| c9be4f6874 | |||
| fbc63b0e32 | |||
| 5f7df0d14f | |||
| ee832206dc | |||
| 1e295c7bbb | |||
| 4fbba931a5 | |||
| 86f19f6cb6 | |||
| df60919bb0 | |||
| 2f1f36eeda | |||
| 1c0a4f8d78 | |||
| cc376ac5ed | |||
| 10c9d2fcec | |||
| 439ffe2e8a | |||
| 4e55262521 | |||
| ebd2ec57fc | |||
| f536819c5d | |||
| af75c6db2f | |||
| d12619cf1f | |||
| 4c1d227776 | |||
| da02b7a141 | |||
| 17117bd21a | |||
| 0d7494ac52 | |||
| a59a33846e | |||
| 51b8ba334a | |||
| abc2269d97 | |||
| ff385aaf7b | |||
| 1b50ca6bd3 | |||
| 6bae759349 | |||
| e1e8c165db | |||
| 6699833121 | |||
| 095acefd7e | |||
| b62e066b7d | |||
| 9969cb6d83 | |||
| 04b3f5a247 | |||
| c91b47fded | |||
| f2c364b491 | |||
| 170adccf80 | |||
| 98390e1e5e | |||
| 6df8c2678b | |||
| 7f49abb6d1 | |||
| b9bf56e41d | |||
| d0e3e2acfc | |||
| 18d983c686 | |||
| d8abbc501e | |||
| 6ce19ff861 | |||
| c8ef49cc8e | |||
| f61983d908 | |||
| 7615e0b036 | |||
| afe22b84c2 | |||
| 634aba4ab6 | |||
| 26a2d3875f | |||
| 802d083df7 | |||
| f5b43a264a | |||
| 59e4755562 | |||
| 2576aa4063 | |||
| 3fbe762832 | |||
| 611bb0b92e | |||
| 32a8b9b25a | |||
| 97cad6ca8e | |||
| 015f7d8ce1 | |||
| da4e2710b4 | |||
| a368040fd6 | |||
| 5dbd3b0bbf | |||
| 197dbffe20 | |||
| 5341e77796 | |||
| f049a6ec16 | |||
| 7203da7133 | |||
| a21df0cc6d | |||
| 83683a13bb | |||
| 59165dd526 | |||
| 25554d0b21 | |||
| 4f86282b14 | |||
| b3237f3eb6 | |||
| fd68fb115d | |||
| 43e047c523 | |||
| 7fdf775394 | |||
| 59084c6b73 | |||
| 4fcc09a02c | |||
| f5b082d3b3 | |||
| c164759c41 | |||
| 2179b67706 | |||
| fbde98f36e | |||
| 529f8ba786 | |||
| f4676bb41c | |||
| 262332a7c9 | |||
| 8b1709b8f3 | |||
| aee33d8b4b | |||
| 83f03976ea | |||
| ffcd83e3a8 | |||
| 9a522946a5 | |||
| 268d029584 | |||
| 85471d0587 | |||
| 96a1a0dec5 | |||
| 40ac055d11 | |||
| c9a6f4282a | |||
| 6ed6c08ace | |||
| e4c57a9b61 | |||
| b0d8a667a1 | |||
| 9c9ee22c2b | |||
| 639dce6282 | |||
| 8e65834c44 | |||
| 64db939e4a | |||
| 3d83f869d9 | |||
| 088a653318 | |||
| bdb1a81a39 | |||
| c2e7b6341c | |||
| e75556bc7b | |||
| d3d40983d6 | |||
| 32adf77b22 | |||
| 1301c7e95d | |||
| 1a057654b2 | |||
| ca3440cb42 | |||
| 48b22292ff | |||
| e0faaa4807 | |||
| 2e4944198d | |||
| 38a1caefb8 | |||
| e731a0a164 | |||
| 0f2efdbe97 | |||
| feeeab1761 | |||
| b4cf471021 | |||
| 82751141ac | |||
| 9f43ee3304 | |||
| 614c7b0f8e | |||
| cc84533d85 | |||
| 6faf61ba40 | |||
| 80a5019534 | |||
| 03bd02a627 | |||
| f16aa4a9b5 | |||
| a3c9e8d4fc | |||
| 3814f12b67 | |||
| ceb881ab05 | |||
| 871464811c |
@@ -0,0 +1,10 @@
|
||||
name: "Validate Gradle Wrapper"
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
validation:
|
||||
name: "Validation"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
@@ -24,6 +24,10 @@ buildSrc/build
|
||||
/src/asciidoc/build
|
||||
target/
|
||||
|
||||
# Projects not in this branch
|
||||
integration-tests/
|
||||
spring-core/kotlin-coroutines/
|
||||
|
||||
# Eclipse artifacts, including WTP generated manifests
|
||||
.classpath
|
||||
.project
|
||||
|
||||
+12
-12
@@ -28,24 +28,24 @@ ext {
|
||||
!it.name.equals("spring-build-src") && !it.name.equals("spring-framework-bom")
|
||||
}
|
||||
|
||||
aspectjVersion = "1.9.4"
|
||||
aspectjVersion = "1.9.5"
|
||||
freemarkerVersion = "2.3.28"
|
||||
groovyVersion = "2.5.8"
|
||||
groovyVersion = "2.5.9"
|
||||
hsqldbVersion = "2.4.1"
|
||||
jackson2Version = "2.9.9"
|
||||
jettyVersion = "9.4.21.v20190926"
|
||||
jettyVersion = "9.4.29.v20200521"
|
||||
junit5Version = "5.3.2"
|
||||
kotlinVersion = "1.2.71"
|
||||
log4jVersion = "2.11.2"
|
||||
nettyVersion = "4.1.43.Final"
|
||||
reactorVersion = "Californium-SR13"
|
||||
nettyVersion = "4.1.50.Final"
|
||||
reactorVersion = "Californium-SR19"
|
||||
rxjavaVersion = "1.3.8"
|
||||
rxjavaAdapterVersion = "1.2.1"
|
||||
rxjava2Version = "2.2.12"
|
||||
slf4jVersion = "1.7.28" // spring-jcl + consistent 3rd party deps
|
||||
rxjava2Version = "2.2.19"
|
||||
slf4jVersion = "1.7.30" // spring-jcl + consistent 3rd party deps
|
||||
tiles3Version = "3.0.8"
|
||||
tomcatVersion = "9.0.26"
|
||||
undertowVersion = "2.0.26.Final"
|
||||
tomcatVersion = "9.0.36"
|
||||
undertowVersion = "2.0.30.Final"
|
||||
|
||||
gradleScriptDir = "${rootProject.projectDir}/gradle"
|
||||
withoutJclOverSlf4j = {
|
||||
@@ -142,13 +142,13 @@ configure(allprojects) { project ->
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
toolVersion = "8.24"
|
||||
toolVersion = "8.33"
|
||||
configDir = rootProject.file("src/checkstyle")
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/libs-release" }
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -184,7 +184,7 @@ configure(allprojects) { project ->
|
||||
"https://tiles.apache.org/tiles-request/apidocs/",
|
||||
"https://tiles.apache.org/framework/apidocs/",
|
||||
"https://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
|
||||
"https://www.ehcache.org/apidocs/2.10.4",
|
||||
"https://www.ehcache.org/apidocs/2.10.4/",
|
||||
"https://www.quartz-scheduler.org/api/2.3.0/",
|
||||
"https://fasterxml.github.io/jackson-core/javadoc/2.9/",
|
||||
"https://fasterxml.github.io/jackson-databind/javadoc/2.9/",
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=5.1.11.BUILD-SNAPSHOT
|
||||
version=5.1.16.RELEASE
|
||||
|
||||
+2
-2
@@ -149,14 +149,14 @@ task schemaZip(type: Zip) {
|
||||
def Properties schemas = new Properties();
|
||||
|
||||
subproject.sourceSets.main.resources.find {
|
||||
it.path.endsWith("META-INF/spring.schemas")
|
||||
(it.path.endsWith("META-INF/spring.schemas") || it.path.endsWith("META-INF\\spring.schemas"))
|
||||
}?.withInputStream { schemas.load(it) }
|
||||
|
||||
for (def key : schemas.keySet()) {
|
||||
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
|
||||
assert shortName != key
|
||||
File xsdFile = subproject.sourceSets.main.resources.find {
|
||||
it.path.endsWith(schemas.get(key))
|
||||
(it.path.endsWith(schemas.get(key)) || it.path.endsWith(schemas.get(key).replaceAll('\\/','\\\\')))
|
||||
}
|
||||
assert xsdFile != null
|
||||
into (shortName) {
|
||||
|
||||
@@ -4,6 +4,6 @@ dependencies {
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-core"))
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.apache.commons:commons-pool2:2.6.0")
|
||||
optional("org.apache.commons:commons-pool2:2.6.2")
|
||||
optional("com.jamonapi:jamon:2.81")
|
||||
}
|
||||
|
||||
+7
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -76,9 +76,8 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
new InstanceComparator<>(
|
||||
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
|
||||
(Converter<Method, Annotation>) method -> {
|
||||
AspectJAnnotation<?> annotation =
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
|
||||
return (annotation != null ? annotation.getAnnotation() : null);
|
||||
AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
|
||||
return (ann != null ? ann.getAnnotation() : null);
|
||||
});
|
||||
Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
|
||||
METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
|
||||
@@ -153,8 +152,10 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
|
||||
methods.add(method);
|
||||
}
|
||||
});
|
||||
methods.sort(METHOD_COMPARATOR);
|
||||
}, ReflectionUtils.USER_DECLARED_METHODS);
|
||||
if (methods.size() > 1) {
|
||||
methods.sort(METHOD_COMPARATOR);
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
|
||||
+3
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -138,14 +138,8 @@ class AspectJPrecedenceComparator implements Comparator<Advisor> {
|
||||
}
|
||||
|
||||
private int getAspectDeclarationOrder(Advisor anAdvisor) {
|
||||
AspectJPrecedenceInformation precedenceInfo =
|
||||
AspectJAopUtils.getAspectJPrecedenceInformationFor(anAdvisor);
|
||||
if (precedenceInfo != null) {
|
||||
return precedenceInfo.getDeclarationOrder();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
AspectJPrecedenceInformation precedenceInfo = AspectJAopUtils.getAspectJPrecedenceInformationFor(anAdvisor);
|
||||
return (precedenceInfo != null ? precedenceInfo.getDeclarationOrder() : 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -61,12 +61,12 @@ public class AopNamespaceHandler extends NamespaceHandlerSupport {
|
||||
*/
|
||||
@Override
|
||||
public void init() {
|
||||
// In 2.0 XSD as well as in 2.1 XSD.
|
||||
// In 2.0 XSD as well as in 2.5+ XSDs
|
||||
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
|
||||
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
|
||||
|
||||
// Only in 2.0 XSD: moved to context namespace as of 2.1
|
||||
// Only in 2.0 XSD: moved to context namespace in 2.5+
|
||||
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -258,15 +258,17 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
int mod = method.getModifiers();
|
||||
if (!Modifier.isStatic(mod) && !Modifier.isPrivate(mod)) {
|
||||
if (Modifier.isFinal(mod)) {
|
||||
if (implementsInterface(method, ifcs)) {
|
||||
if (logger.isInfoEnabled() && implementsInterface(method, ifcs)) {
|
||||
logger.info("Unable to proxy interface-implementing method [" + method + "] because " +
|
||||
"it is marked as final: Consider using interface-based JDK proxies instead!");
|
||||
}
|
||||
logger.debug("Final method [" + method + "] cannot get proxied via CGLIB: " +
|
||||
"Calls to this method will NOT be routed to the target instance and " +
|
||||
"might lead to NPEs against uninitialized fields in the proxy instance.");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Final method [" + method + "] cannot get proxied via CGLIB: " +
|
||||
"Calls to this method will NOT be routed to the target instance and " +
|
||||
"might lead to NPEs against uninitialized fields in the proxy instance.");
|
||||
}
|
||||
}
|
||||
else if (!Modifier.isPublic(mod) && !Modifier.isProtected(mod) &&
|
||||
else if (logger.isDebugEnabled() && !Modifier.isPublic(mod) && !Modifier.isProtected(mod) &&
|
||||
proxyClassLoader != null && proxySuperClass.getClassLoader() != proxyClassLoader) {
|
||||
logger.debug("Method [" + method + "] is package-visible across different ClassLoaders " +
|
||||
"and cannot get proxied via CGLIB: Declare this method as public or protected " +
|
||||
@@ -526,7 +528,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
private static class StaticDispatcher implements Dispatcher, Serializable {
|
||||
|
||||
@Nullable
|
||||
private Object target;
|
||||
private final Object target;
|
||||
|
||||
public StaticDispatcher(@Nullable Object target) {
|
||||
this.target = target;
|
||||
@@ -552,7 +554,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object loadObject() throws Exception {
|
||||
public Object loadObject() {
|
||||
return this.advised;
|
||||
}
|
||||
}
|
||||
@@ -940,11 +942,11 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean equalsAdviceClasses(Advisor a, Advisor b) {
|
||||
private static boolean equalsAdviceClasses(Advisor a, Advisor b) {
|
||||
return (a.getAdvice().getClass() == b.getAdvice().getClass());
|
||||
}
|
||||
|
||||
private boolean equalsPointcuts(Advisor a, Advisor b) {
|
||||
private static boolean equalsPointcuts(Advisor a, Advisor b) {
|
||||
// If only one of the advisor (but not both) is PointcutAdvisor, then it is a mismatch.
|
||||
// Takes care of the situations where an IntroductionAdvisor is used (see SPR-3959).
|
||||
return (!(a instanceof PointcutAdvisor) ||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -21,9 +21,7 @@ import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.aopalliance.intercept.Interceptor;
|
||||
@@ -342,11 +340,8 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
// an independent instance of the configuration.
|
||||
// In this case, no proxy will have an instance of this object's configuration,
|
||||
// but will have an independent copy.
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Creating copy of prototype ProxyFactoryBean config: " + this);
|
||||
}
|
||||
|
||||
ProxyCreatorSupport copy = new ProxyCreatorSupport(getAopProxyFactory());
|
||||
|
||||
// The copy needs a fresh advisor chain, and a fresh TargetSource.
|
||||
TargetSource targetSource = freshTargetSource();
|
||||
copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain());
|
||||
@@ -359,9 +354,6 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
}
|
||||
copy.setFrozen(this.freezeProxy);
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Using ProxyCreatorSupport copy: " + copy);
|
||||
}
|
||||
return getProxy(copy.createAopProxy());
|
||||
}
|
||||
|
||||
@@ -395,9 +387,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
logger.debug("Bean with name '" + finalName + "' concluding interceptor chain " +
|
||||
"is not an advisor class: treating it as a target or TargetSource");
|
||||
}
|
||||
String[] newNames = new String[this.interceptorNames.length - 1];
|
||||
System.arraycopy(this.interceptorNames, 0, newNames, 0, newNames.length);
|
||||
this.interceptorNames = newNames;
|
||||
this.interceptorNames = Arrays.copyOf(this.interceptorNames, this.interceptorNames.length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -449,16 +439,12 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
|
||||
// Materialize interceptor chain from bean names.
|
||||
for (String name : this.interceptorNames) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Configuring advisor or advice '" + name + "'");
|
||||
}
|
||||
|
||||
if (name.endsWith(GLOBAL_SUFFIX)) {
|
||||
if (!(this.beanFactory instanceof ListableBeanFactory)) {
|
||||
throw new AopConfigException(
|
||||
"Can only use global advisors or interceptors with a ListableBeanFactory");
|
||||
}
|
||||
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
|
||||
addGlobalAdvisors((ListableBeanFactory) this.beanFactory,
|
||||
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
|
||||
}
|
||||
|
||||
@@ -475,7 +461,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
|
||||
advice = new PrototypePlaceholderAdvisor(name);
|
||||
}
|
||||
addAdvisorOnChainCreation(advice, name);
|
||||
addAdvisorOnChainCreation(advice);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -498,11 +484,10 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Refreshing bean named '" + pa.getBeanName() + "'");
|
||||
}
|
||||
// Replace the placeholder with a fresh prototype instance resulting
|
||||
// from a getBean() lookup
|
||||
// Replace the placeholder with a fresh prototype instance resulting from a getBean lookup
|
||||
if (this.beanFactory == null) {
|
||||
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
|
||||
"- cannot resolve prototype advisor '" + pa.getBeanName() + "'");
|
||||
throw new IllegalStateException("No BeanFactory available anymore (probably due to " +
|
||||
"serialization) - cannot resolve prototype advisor '" + pa.getBeanName() + "'");
|
||||
}
|
||||
Object bean = this.beanFactory.getBean(pa.getBeanName());
|
||||
Advisor refreshedAdvisor = namedBeanToAdvisor(bean);
|
||||
@@ -519,28 +504,26 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
/**
|
||||
* Add all global interceptors and pointcuts.
|
||||
*/
|
||||
private void addGlobalAdvisor(ListableBeanFactory beanFactory, String prefix) {
|
||||
private void addGlobalAdvisors(ListableBeanFactory beanFactory, String prefix) {
|
||||
String[] globalAdvisorNames =
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Advisor.class);
|
||||
String[] globalInterceptorNames =
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Interceptor.class);
|
||||
List<Object> beans = new ArrayList<>(globalAdvisorNames.length + globalInterceptorNames.length);
|
||||
Map<Object, String> names = new HashMap<>(beans.size());
|
||||
for (String name : globalAdvisorNames) {
|
||||
Object bean = beanFactory.getBean(name);
|
||||
beans.add(bean);
|
||||
names.put(bean, name);
|
||||
}
|
||||
for (String name : globalInterceptorNames) {
|
||||
Object bean = beanFactory.getBean(name);
|
||||
beans.add(bean);
|
||||
names.put(bean, name);
|
||||
}
|
||||
AnnotationAwareOrderComparator.sort(beans);
|
||||
for (Object bean : beans) {
|
||||
String name = names.get(bean);
|
||||
if (name.startsWith(prefix)) {
|
||||
addAdvisorOnChainCreation(bean, name);
|
||||
if (globalAdvisorNames.length > 0 || globalInterceptorNames.length > 0) {
|
||||
List<Object> beans = new ArrayList<>(globalAdvisorNames.length + globalInterceptorNames.length);
|
||||
for (String name : globalAdvisorNames) {
|
||||
if (name.startsWith(prefix)) {
|
||||
beans.add(beanFactory.getBean(name));
|
||||
}
|
||||
}
|
||||
for (String name : globalInterceptorNames) {
|
||||
if (name.startsWith(prefix)) {
|
||||
beans.add(beanFactory.getBean(name));
|
||||
}
|
||||
}
|
||||
AnnotationAwareOrderComparator.sort(beans);
|
||||
for (Object bean : beans) {
|
||||
addAdvisorOnChainCreation(bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -551,17 +534,11 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
* Because of these three possibilities, we can't type the signature
|
||||
* more strongly.
|
||||
* @param next advice, advisor or target object
|
||||
* @param name bean name from which we obtained this object in our owning
|
||||
* bean factory
|
||||
*/
|
||||
private void addAdvisorOnChainCreation(Object next, String name) {
|
||||
private void addAdvisorOnChainCreation(Object next) {
|
||||
// We need to convert to an Advisor if necessary so that our source reference
|
||||
// matches what we find from superclass interceptors.
|
||||
Advisor advisor = namedBeanToAdvisor(next);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Adding advisor with name '" + name + "'");
|
||||
}
|
||||
addAdvisor(advisor);
|
||||
addAdvisor(namedBeanToAdvisor(next));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -572,9 +549,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
*/
|
||||
private TargetSource freshTargetSource() {
|
||||
if (this.targetName == null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Not refreshing target: Bean name not specified in 'interceptorNames'.");
|
||||
}
|
||||
// Not refreshing target: bean name not specified in 'interceptorNames'
|
||||
return this.targetSource;
|
||||
}
|
||||
else {
|
||||
@@ -602,8 +577,8 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
// We expected this to be an Advisor or Advice,
|
||||
// but it wasn't. This is a configuration error.
|
||||
throw new AopConfigException("Unknown advisor type " + next.getClass() +
|
||||
"; Can only include Advisor or Advice type beans in interceptorNames chain except for last entry," +
|
||||
"which may also be target or TargetSource", ex);
|
||||
"; can only include Advisor or Advice type beans in interceptorNames chain " +
|
||||
"except for last entry which may also be target instance or TargetSource", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,7 +589,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
protected void adviceChanged() {
|
||||
super.adviceChanged();
|
||||
if (this.singleton) {
|
||||
logger.debug("Advice has changed; recaching singleton instance");
|
||||
logger.debug("Advice has changed; re-caching singleton instance");
|
||||
synchronized (this) {
|
||||
this.singletonInstance = null;
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -37,6 +37,7 @@ import org.springframework.scheduling.config.TaskManagementConfigUtils;
|
||||
* @see org.springframework.scheduling.annotation.ProxyAsyncConfiguration
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class AspectJAsyncConfiguration extends AbstractAsyncConfiguration {
|
||||
|
||||
@Bean(name = TaskManagementConfigUtils.ASYNC_EXECUTION_ASPECT_BEAN_NAME)
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -36,6 +36,7 @@ import org.springframework.transaction.config.TransactionManagementConfigUtils;
|
||||
* @see TransactionManagementConfigurationSelector
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class AspectJJtaTransactionManagementConfiguration extends AspectJTransactionManagementConfiguration {
|
||||
|
||||
@Bean(name = TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_BEAN_NAME)
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -38,6 +38,7 @@ import org.springframework.transaction.config.TransactionManagementConfigUtils;
|
||||
* @see AspectJJtaTransactionManagementConfiguration
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class AspectJTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
|
||||
|
||||
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME)
|
||||
|
||||
@@ -9,7 +9,7 @@ dependencies {
|
||||
optional("org.codehaus.groovy:groovy-xml:${groovyVersion}")
|
||||
optional("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
|
||||
optional("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
|
||||
testCompile("javax.annotation:javax.annotation-api:1.3.2")
|
||||
}
|
||||
|
||||
// This module does joint compilation for Java and Groovy code with the compileGroovy task.
|
||||
|
||||
+5
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -43,9 +43,9 @@ import org.springframework.util.StringUtils;
|
||||
* Internal class that caches JavaBeans {@link java.beans.PropertyDescriptor}
|
||||
* information for a Java class. Not intended for direct use by application code.
|
||||
*
|
||||
* <p>Necessary for own caching of descriptors within the application's
|
||||
* ClassLoader, rather than rely on the JDK's system-wide BeanInfo cache
|
||||
* (in order to avoid leaks on ClassLoader shutdown).
|
||||
* <p>Necessary for Spring's own caching of bean descriptors within the application
|
||||
* {@link ClassLoader}, rather than relying on the JDK's system-wide {@link BeanInfo}
|
||||
* cache (in order to avoid leaks on individual application shutdown in a shared JVM).
|
||||
*
|
||||
* <p>Information is cached statically, so we don't need to create new
|
||||
* objects of this class for every JavaBean we manipulate. Hence, this class
|
||||
@@ -97,7 +97,7 @@ public final class CachedIntrospectionResults {
|
||||
SpringProperties.getFlag(IGNORE_BEANINFO_PROPERTY_NAME);
|
||||
|
||||
/** Stores the BeanInfoFactory instances. */
|
||||
private static List<BeanInfoFactory> beanInfoFactories = SpringFactoriesLoader.loadFactories(
|
||||
private static final List<BeanInfoFactory> beanInfoFactories = SpringFactoriesLoader.loadFactories(
|
||||
BeanInfoFactory.class, CachedIntrospectionResults.class.getClassLoader());
|
||||
|
||||
private static final Log logger = LogFactory.getLog(CachedIntrospectionResults.class);
|
||||
@@ -163,7 +163,6 @@ public final class CachedIntrospectionResults {
|
||||
* @return the corresponding CachedIntrospectionResults
|
||||
* @throws BeansException in case of introspection failure
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static CachedIntrospectionResults forClass(Class<?> beanClass) throws BeansException {
|
||||
CachedIntrospectionResults results = strongClassCache.get(beanClass);
|
||||
if (results != null) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -41,8 +41,8 @@ import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Decorator for a standard {@link BeanInfo} object, e.g. as created by
|
||||
* {@link Introspector#getBeanInfo(Class)}, designed to discover and register static
|
||||
* and/or non-void returning setter methods. For example:
|
||||
* {@link Introspector#getBeanInfo(Class)}, designed to discover and register
|
||||
* static and/or non-void returning setter methods. For example:
|
||||
*
|
||||
* <pre class="code">
|
||||
* public class Bean {
|
||||
@@ -145,11 +145,10 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
|
||||
public static boolean isCandidateWriteMethod(Method method) {
|
||||
String methodName = method.getName();
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
int nParams = parameterTypes.length;
|
||||
int nParams = method.getParameterCount();
|
||||
return (methodName.length() > 3 && methodName.startsWith("set") && Modifier.isPublic(method.getModifiers()) &&
|
||||
(!void.class.isAssignableFrom(method.getReturnType()) || Modifier.isStatic(method.getModifiers())) &&
|
||||
(nParams == 1 || (nParams == 2 && int.class == parameterTypes[0])));
|
||||
(nParams == 1 || (nParams == 2 && int.class == method.getParameterTypes()[0])));
|
||||
}
|
||||
|
||||
private void handleCandidateWriteMethod(Method method) throws IntrospectionException {
|
||||
@@ -209,7 +208,7 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
}
|
||||
|
||||
private String propertyNameFor(Method method) {
|
||||
return Introspector.decapitalize(method.getName().substring(3, method.getName().length()));
|
||||
return Introspector.decapitalize(method.getName().substring(3));
|
||||
}
|
||||
|
||||
|
||||
@@ -488,7 +487,7 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
}
|
||||
|
||||
/*
|
||||
* See java.beans.IndexedPropertyDescriptor#equals(java.lang.Object)
|
||||
* See java.beans.IndexedPropertyDescriptor#equals
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
@@ -535,11 +534,13 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
public int compare(PropertyDescriptor desc1, PropertyDescriptor desc2) {
|
||||
String left = desc1.getName();
|
||||
String right = desc2.getName();
|
||||
byte[] leftBytes = left.getBytes();
|
||||
byte[] rightBytes = right.getBytes();
|
||||
for (int i = 0; i < left.length(); i++) {
|
||||
if (right.length() == i) {
|
||||
return 1;
|
||||
}
|
||||
int result = left.getBytes()[i] - right.getBytes()[i];
|
||||
int result = leftBytes[i] - rightBytes[i];
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -66,8 +66,7 @@ abstract class PropertyDescriptorUtils {
|
||||
Class<?> propertyType = null;
|
||||
|
||||
if (readMethod != null) {
|
||||
Class<?>[] params = readMethod.getParameterTypes();
|
||||
if (params.length != 0) {
|
||||
if (readMethod.getParameterCount() != 0) {
|
||||
throw new IntrospectionException("Bad read method arg count: " + readMethod);
|
||||
}
|
||||
propertyType = readMethod.getReturnType();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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,10 +39,16 @@ import org.springframework.lang.Nullable;
|
||||
*
|
||||
* <p><b>{@code FactoryBean} is a programmatic contract. Implementations are not
|
||||
* supposed to rely on annotation-driven injection or other reflective facilities.</b>
|
||||
* {@link #getObjectType()} {@link #getObject()} invocations may arrive early in
|
||||
* the bootstrap process, even ahead of any post-processor setup. If you need access
|
||||
* {@link #getObjectType()} {@link #getObject()} invocations may arrive early in the
|
||||
* bootstrap process, even ahead of any post-processor setup. If you need access to
|
||||
* other beans, implement {@link BeanFactoryAware} and obtain them programmatically.
|
||||
*
|
||||
* <p><b>The container is only responsible for managing the lifecycle of the FactoryBean
|
||||
* instance, not the lifecycle of the objects created by the FactoryBean.</b> Therefore,
|
||||
* a destroy method on an exposed bean object (such as {@link java.io.Closeable#close()}
|
||||
* will <i>not</i> be called automatically. Instead, a FactoryBean should implement
|
||||
* {@link DisposableBean} and delegate any such close call to the underlying object.
|
||||
*
|
||||
* <p>Finally, FactoryBean objects participate in the containing BeanFactory's
|
||||
* synchronization of bean creation. There is usually no need for internal
|
||||
* synchronization other than for purposes of lazy initialization within the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -41,12 +41,11 @@ import java.lang.annotation.Target;
|
||||
* regular constructors: i.e. lookup methods cannot get replaced on beans returned
|
||||
* from factory methods where we cannot dynamically provide a subclass for them.
|
||||
*
|
||||
* <p><b>Concrete limitations in typical Spring configuration scenarios:</b>
|
||||
* When used with component scanning or any other mechanism that filters out abstract
|
||||
* beans, provide stub implementations of your lookup methods to be able to declare
|
||||
* them as concrete classes. And please remember that lookup methods won't work on
|
||||
* beans returned from {@code @Bean} methods in configuration classes; you'll have
|
||||
* to resort to {@code @Inject Provider<TargetBean>} or the like instead.
|
||||
* <p><b>Recommendations for typical Spring configuration scenarios:</b>
|
||||
* When a concrete class may be needed in certain scenarios, consider providing stub
|
||||
* implementations of your lookup methods. And please remember that lookup methods
|
||||
* won't work on beans returned from {@code @Bean} methods in configuration classes;
|
||||
* you'll have to resort to {@code @Inject Provider<TargetBean>} or the like instead.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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 DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
|
||||
/**
|
||||
* Determine the name of the wrapped parameter/field.
|
||||
* @return the declared name (never {@code null})
|
||||
* @return the declared name (may be {@code null} if unresolvable)
|
||||
*/
|
||||
@Nullable
|
||||
public String getDependencyName() {
|
||||
|
||||
+60
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -25,17 +25,23 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.LoaderOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.constructor.Constructor;
|
||||
import org.yaml.snakeyaml.reader.UnicodeReader;
|
||||
import org.yaml.snakeyaml.representer.Representer;
|
||||
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -45,6 +51,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
public abstract class YamlProcessor {
|
||||
@@ -59,6 +66,8 @@ public abstract class YamlProcessor {
|
||||
|
||||
private boolean matchDefault = true;
|
||||
|
||||
private Set<String> supportedTypes = Collections.emptySet();
|
||||
|
||||
|
||||
/**
|
||||
* A map of document matchers allowing callers to selectively use only
|
||||
@@ -117,6 +126,27 @@ public abstract class YamlProcessor {
|
||||
this.resources = resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the supported types that can be loaded from YAML documents.
|
||||
* <p>If no supported types are configured, all types encountered in YAML
|
||||
* documents will be supported. If an unsupported type is encountered, an
|
||||
* {@link IllegalStateException} will be thrown when the corresponding YAML
|
||||
* node is processed.
|
||||
* @param supportedTypes the supported types, or an empty array to clear the
|
||||
* supported types
|
||||
* @since 5.1.16
|
||||
* @see #createYaml()
|
||||
*/
|
||||
public void setSupportedTypes(Class<?>... supportedTypes) {
|
||||
if (ObjectUtils.isEmpty(supportedTypes)) {
|
||||
this.supportedTypes = Collections.emptySet();
|
||||
}
|
||||
else {
|
||||
Assert.noNullElements(supportedTypes, "'supportedTypes' must not contain null elements");
|
||||
this.supportedTypes = Arrays.stream(supportedTypes).map(Class::getName)
|
||||
.collect(Collectors.collectingAndThen(Collectors.toSet(), Collections::unmodifiableSet));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide an opportunity for subclasses to process the Yaml parsed from the supplied
|
||||
@@ -142,12 +172,22 @@ public abstract class YamlProcessor {
|
||||
* Create the {@link Yaml} instance to use.
|
||||
* <p>The default implementation sets the "allowDuplicateKeys" flag to {@code false},
|
||||
* enabling built-in duplicate key handling in SnakeYAML 1.18+.
|
||||
* <p>As of Spring Framework 5.1.16, if custom {@linkplain #setSupportedTypes
|
||||
* supported types} have been configured, the default implementation creates
|
||||
* a {@code Yaml} instance that filters out unsupported types encountered in
|
||||
* YAML documents. If an unsupported type is encountered, an
|
||||
* {@link IllegalStateException} will be thrown when the node is processed.
|
||||
* @see LoaderOptions#setAllowDuplicateKeys(boolean)
|
||||
*/
|
||||
protected Yaml createYaml() {
|
||||
LoaderOptions options = new LoaderOptions();
|
||||
options.setAllowDuplicateKeys(false);
|
||||
return new Yaml(options);
|
||||
LoaderOptions loaderOptions = new LoaderOptions();
|
||||
loaderOptions.setAllowDuplicateKeys(false);
|
||||
|
||||
if (!this.supportedTypes.isEmpty()) {
|
||||
return new Yaml(new FilteringConstructor(), new Representer(),
|
||||
new DumperOptions(), loaderOptions);
|
||||
}
|
||||
return new Yaml(loaderOptions);
|
||||
}
|
||||
|
||||
private boolean process(MatchCallback callback, Yaml yaml, Resource resource) {
|
||||
@@ -388,4 +428,20 @@ public abstract class YamlProcessor {
|
||||
FIRST_FOUND
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@link Constructor} that supports filtering of unsupported types.
|
||||
* <p>If an unsupported type is encountered in a YAML document, an
|
||||
* {@link IllegalStateException} will be thrown from {@link #getClassForName}.
|
||||
*/
|
||||
private class FilteringConstructor extends Constructor {
|
||||
|
||||
@Override
|
||||
protected Class<?> getClassForName(String name) throws ClassNotFoundException {
|
||||
Assert.state(YamlProcessor.this.supportedTypes.contains(name),
|
||||
() -> "Unsupported type encountered in YAML document: " + name);
|
||||
return super.getClassForName(name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+45
-31
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -182,10 +182,12 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setMetaClass(MetaClass metaClass) {
|
||||
this.metaClass = metaClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaClass getMetaClass() {
|
||||
return this.metaClass;
|
||||
}
|
||||
@@ -216,6 +218,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
* @return the number of bean definitions found
|
||||
* @throws BeanDefinitionStoreException in case of loading or parsing errors
|
||||
*/
|
||||
@Override
|
||||
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
|
||||
return loadBeanDefinitions(new EncodedResource(resource));
|
||||
}
|
||||
@@ -240,10 +243,11 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
logger.trace("Loading Groovy bean definitions from " + encodedResource);
|
||||
}
|
||||
|
||||
Closure beans = new Closure(this) {
|
||||
@SuppressWarnings("serial")
|
||||
Closure<Object> beans = new Closure<Object>(this) {
|
||||
@Override
|
||||
public Object call(Object[] args) {
|
||||
invokeBeanDefiningClosure((Closure) args[0]);
|
||||
public Object call(Object... args) {
|
||||
invokeBeanDefiningClosure((Closure<?>) args[0]);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -285,7 +289,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
* @param closure the block or closure
|
||||
* @return this {@code GroovyBeanDefinitionReader} instance
|
||||
*/
|
||||
public GroovyBeanDefinitionReader beans(Closure closure) {
|
||||
public GroovyBeanDefinitionReader beans(Closure<?> closure) {
|
||||
return invokeBeanDefiningClosure(closure);
|
||||
}
|
||||
|
||||
@@ -309,25 +313,22 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
public AbstractBeanDefinition bean(Class<?> type, Object...args) {
|
||||
GroovyBeanDefinitionWrapper current = this.currentBeanDefinition;
|
||||
try {
|
||||
Closure callable = null;
|
||||
Collection constructorArgs = null;
|
||||
Closure<?> callable = null;
|
||||
Collection<Object> constructorArgs = null;
|
||||
if (!ObjectUtils.isEmpty(args)) {
|
||||
int index = args.length;
|
||||
Object lastArg = args[index - 1];
|
||||
if (lastArg instanceof Closure) {
|
||||
callable = (Closure) lastArg;
|
||||
if (lastArg instanceof Closure<?>) {
|
||||
callable = (Closure<?>) lastArg;
|
||||
index--;
|
||||
}
|
||||
if (index > -1) {
|
||||
constructorArgs = resolveConstructorArguments(args, 0, index);
|
||||
}
|
||||
constructorArgs = resolveConstructorArguments(args, 0, index);
|
||||
}
|
||||
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(null, type, constructorArgs);
|
||||
if (callable != null) {
|
||||
callable.call(this.currentBeanDefinition);
|
||||
}
|
||||
return this.currentBeanDefinition.getBeanDefinition();
|
||||
|
||||
}
|
||||
finally {
|
||||
this.currentBeanDefinition = current;
|
||||
@@ -373,10 +374,11 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
* This method overrides method invocation to create beans for each method name that
|
||||
* takes a class argument.
|
||||
*/
|
||||
@Override
|
||||
public Object invokeMethod(String name, Object arg) {
|
||||
Object[] args = (Object[])arg;
|
||||
if ("beans".equals(name) && args.length == 1 && args[0] instanceof Closure) {
|
||||
return beans((Closure) args[0]);
|
||||
return beans((Closure<?>) args[0]);
|
||||
}
|
||||
else if ("ref".equals(name)) {
|
||||
String refName;
|
||||
@@ -429,10 +431,10 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
private void finalizeDeferredProperties() {
|
||||
for (DeferredProperty dp : this.deferredProperties.values()) {
|
||||
if (dp.value instanceof List) {
|
||||
dp.value = manageListIfNecessary((List) dp.value);
|
||||
dp.value = manageListIfNecessary((List<?>) dp.value);
|
||||
}
|
||||
else if (dp.value instanceof Map) {
|
||||
dp.value = manageMapIfNecessary((Map) dp.value);
|
||||
dp.value = manageMapIfNecessary((Map<?, ?>) dp.value);
|
||||
}
|
||||
dp.apply();
|
||||
}
|
||||
@@ -444,7 +446,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
* @param callable the closure argument
|
||||
* @return this {@code GroovyBeanDefinitionReader} instance
|
||||
*/
|
||||
protected GroovyBeanDefinitionReader invokeBeanDefiningClosure(Closure callable) {
|
||||
protected GroovyBeanDefinitionReader invokeBeanDefiningClosure(Closure<?> callable) {
|
||||
callable.setDelegate(this);
|
||||
callable.call();
|
||||
finalizeDeferredProperties();
|
||||
@@ -483,9 +485,10 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
else if (args[0] instanceof Map) {
|
||||
// named constructor arguments
|
||||
if (args.length > 1 && args[1] instanceof Class) {
|
||||
List constructorArgs = resolveConstructorArguments(args, 2, hasClosureArgument ? args.length - 1 : args.length);
|
||||
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName, (Class)args[1], constructorArgs);
|
||||
Map namedArgs = (Map)args[0];
|
||||
List<Object> constructorArgs =
|
||||
resolveConstructorArguments(args, 2, hasClosureArgument ? args.length - 1 : args.length);
|
||||
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName, (Class<?>) args[1], constructorArgs);
|
||||
Map<?, ?> namedArgs = (Map<?, ?>) args[0];
|
||||
for (Object o : namedArgs.keySet()) {
|
||||
String propName = (String) o;
|
||||
setProperty(propName, namedArgs.get(propName));
|
||||
@@ -494,8 +497,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
// factory method syntax
|
||||
else {
|
||||
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName);
|
||||
//First arg is the map containing factoryBean : factoryMethod
|
||||
Map.Entry factoryBeanEntry = (Map.Entry) ((Map) args[0]).entrySet().iterator().next();
|
||||
// First arg is the map containing factoryBean : factoryMethod
|
||||
Map.Entry<?, ?> factoryBeanEntry = ((Map<?, ?>) args[0]).entrySet().iterator().next();
|
||||
// If we have a closure body, that will be the last argument.
|
||||
// In between are the constructor args
|
||||
int constructorArgsTest = (hasClosureArgument ? 2 : 1);
|
||||
@@ -519,12 +522,13 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
this.currentBeanDefinition.getBeanDefinition().setAbstract(true);
|
||||
}
|
||||
else {
|
||||
List constructorArgs = resolveConstructorArguments(args, 0, hasClosureArgument ? args.length - 1 : args.length);
|
||||
List<Object> constructorArgs =
|
||||
resolveConstructorArguments(args, 0, hasClosureArgument ? args.length - 1 : args.length);
|
||||
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName, null, constructorArgs);
|
||||
}
|
||||
|
||||
if (hasClosureArgument) {
|
||||
Closure callable = (Closure) args[args.length - 1];
|
||||
Closure<?> callable = (Closure<?>) args[args.length - 1];
|
||||
callable.setDelegate(this);
|
||||
callable.setResolveStrategy(Closure.DELEGATE_FIRST);
|
||||
callable.call(this.currentBeanDefinition);
|
||||
@@ -544,10 +548,10 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
constructorArgs[i] = constructorArgs[i].toString();
|
||||
}
|
||||
else if (constructorArgs[i] instanceof List) {
|
||||
constructorArgs[i] = manageListIfNecessary((List) constructorArgs[i]);
|
||||
constructorArgs[i] = manageListIfNecessary((List<?>) constructorArgs[i]);
|
||||
}
|
||||
else if (constructorArgs[i] instanceof Map){
|
||||
constructorArgs[i] = manageMapIfNecessary((Map) constructorArgs[i]);
|
||||
constructorArgs[i] = manageMapIfNecessary((Map<?, ?>) constructorArgs[i]);
|
||||
}
|
||||
}
|
||||
return Arrays.asList(constructorArgs);
|
||||
@@ -601,6 +605,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
* This method overrides property setting in the scope of the {@code GroovyBeanDefinitionReader}
|
||||
* to set properties on the current bean definition.
|
||||
*/
|
||||
@Override
|
||||
public void setProperty(String name, Object value) {
|
||||
if (this.currentBeanDefinition != null) {
|
||||
applyPropertyToBeanDefinition(name, value);
|
||||
@@ -617,7 +622,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
else if (value instanceof Closure) {
|
||||
GroovyBeanDefinitionWrapper current = this.currentBeanDefinition;
|
||||
try {
|
||||
Closure callable = (Closure) value;
|
||||
Closure<?> callable = (Closure<?>) value;
|
||||
Class<?> parameterType = callable.getParameterTypes()[0];
|
||||
if (Object.class == parameterType) {
|
||||
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper("");
|
||||
@@ -647,6 +652,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
* properties from the {@code GroovyBeanDefinitionReader} itself
|
||||
* </ul>
|
||||
*/
|
||||
@Override
|
||||
public Object getProperty(String name) {
|
||||
Binding binding = getBinding();
|
||||
if (binding != null && binding.hasVariable(name)) {
|
||||
@@ -690,8 +696,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
|
||||
private GroovyDynamicElementReader createDynamicElementReader(String namespace) {
|
||||
XmlReaderContext readerContext = this.groovyDslXmlBeanDefinitionReader.createReaderContext(new DescriptiveResource(
|
||||
"Groovy"));
|
||||
XmlReaderContext readerContext = this.groovyDslXmlBeanDefinitionReader.createReaderContext(
|
||||
new DescriptiveResource("Groovy"));
|
||||
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
|
||||
boolean decorating = (this.currentBeanDefinition != null);
|
||||
if (!decorating) {
|
||||
@@ -749,10 +755,12 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
this.metaClass = InvokerHelper.getMetaClass(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaClass getMetaClass() {
|
||||
return this.metaClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getProperty(String property) {
|
||||
if (property.equals("beanName")) {
|
||||
return getBeanName();
|
||||
@@ -769,14 +777,17 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invokeMethod(String name, Object args) {
|
||||
return this.metaClass.invokeMethod(this, name, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMetaClass(MetaClass metaClass) {
|
||||
this.metaClass = metaClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(String property, Object newValue) {
|
||||
if (!addDeferredProperty(property, newValue)) {
|
||||
this.beanDefinition.getBeanDefinition().getPropertyValues().add(property, newValue);
|
||||
@@ -785,7 +796,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
|
||||
|
||||
/**
|
||||
* Wraps a bean definition property an ensures that any RuntimeBeanReference
|
||||
* Wraps a bean definition property and ensures that any RuntimeBeanReference
|
||||
* additions to it are deferred for resolution later.
|
||||
*/
|
||||
private class GroovyPropertyValue extends GroovyObjectSupport {
|
||||
@@ -799,18 +810,21 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
this.propertyValue = propertyValue;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void leftShift(Object value) {
|
||||
InvokerHelper.invokeMethod(this.propertyValue, "leftShift", value);
|
||||
updateDeferredProperties(value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public boolean add(Object value) {
|
||||
boolean retVal = (Boolean) InvokerHelper.invokeMethod(this.propertyValue, "add", value);
|
||||
updateDeferredProperties(value);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public boolean addAll(Collection values) {
|
||||
@SuppressWarnings("unused")
|
||||
public boolean addAll(Collection<?> values) {
|
||||
boolean retVal = (Boolean) InvokerHelper.invokeMethod(this.propertyValue, "addAll", values);
|
||||
for (Object value : values) {
|
||||
updateDeferredProperties(value);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -196,7 +196,7 @@ class GroovyBeanDefinitionWrapper extends GroovyObjectSupport {
|
||||
// constructorArgs
|
||||
else if (CONSTRUCTOR_ARGS.equals(property) && newValue instanceof List) {
|
||||
ConstructorArgumentValues cav = new ConstructorArgumentValues();
|
||||
List args = (List) newValue;
|
||||
List<?> args = (List<?>) newValue;
|
||||
for (Object arg : args) {
|
||||
cav.addGenericArgumentValue(arg);
|
||||
}
|
||||
|
||||
+6
-13
@@ -645,7 +645,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
@Nullable
|
||||
protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
|
||||
Class<?> targetType = determineTargetType(beanName, mbd, typesToMatch);
|
||||
|
||||
// Apply SmartInstantiationAwareBeanPostProcessors to predict the
|
||||
// eventual type after a before-instantiation shortcut.
|
||||
if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
|
||||
@@ -1364,34 +1363,28 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
|
||||
// state of the bean before properties are set. This can be used, for example,
|
||||
// to support styles of field injection.
|
||||
boolean continueWithPropertyPopulation = true;
|
||||
|
||||
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
|
||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||
if (bp instanceof InstantiationAwareBeanPostProcessor) {
|
||||
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
|
||||
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
|
||||
continueWithPropertyPopulation = false;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!continueWithPropertyPopulation) {
|
||||
return;
|
||||
}
|
||||
|
||||
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
|
||||
|
||||
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
|
||||
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
|
||||
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
|
||||
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
|
||||
// Add property values based on autowire by name if applicable.
|
||||
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
|
||||
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
|
||||
autowireByName(beanName, mbd, bw, newPvs);
|
||||
}
|
||||
// Add property values based on autowire by type if applicable.
|
||||
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
|
||||
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
|
||||
autowireByType(beanName, mbd, bw, newPvs);
|
||||
}
|
||||
pvs = newPvs;
|
||||
@@ -1495,7 +1488,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
if (Object.class != pd.getPropertyType()) {
|
||||
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
|
||||
// Do not allow eager init for type matching in case of a prioritized post-processor.
|
||||
boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
|
||||
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
|
||||
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
|
||||
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
|
||||
if (autowiredArgument != null) {
|
||||
|
||||
+24
-24
@@ -1127,30 +1127,30 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
return false;
|
||||
}
|
||||
AbstractBeanDefinition that = (AbstractBeanDefinition) other;
|
||||
boolean rtn = ObjectUtils.nullSafeEquals(getBeanClassName(), that.getBeanClassName());
|
||||
rtn = rtn &= ObjectUtils.nullSafeEquals(this.scope, that.scope);
|
||||
rtn = rtn &= this.abstractFlag == that.abstractFlag;
|
||||
rtn = rtn &= this.lazyInit == that.lazyInit;
|
||||
rtn = rtn &= this.autowireMode == that.autowireMode;
|
||||
rtn = rtn &= this.dependencyCheck == that.dependencyCheck;
|
||||
rtn = rtn &= Arrays.equals(this.dependsOn, that.dependsOn);
|
||||
rtn = rtn &= this.autowireCandidate == that.autowireCandidate;
|
||||
rtn = rtn &= ObjectUtils.nullSafeEquals(this.qualifiers, that.qualifiers);
|
||||
rtn = rtn &= this.primary == that.primary;
|
||||
rtn = rtn &= this.nonPublicAccessAllowed == that.nonPublicAccessAllowed;
|
||||
rtn = rtn &= this.lenientConstructorResolution == that.lenientConstructorResolution;
|
||||
rtn = rtn &= ObjectUtils.nullSafeEquals(this.constructorArgumentValues, that.constructorArgumentValues);
|
||||
rtn = rtn &= ObjectUtils.nullSafeEquals(this.propertyValues, that.propertyValues);
|
||||
rtn = rtn &= ObjectUtils.nullSafeEquals(this.methodOverrides, that.methodOverrides);
|
||||
rtn = rtn &= ObjectUtils.nullSafeEquals(this.factoryBeanName, that.factoryBeanName);
|
||||
rtn = rtn &= ObjectUtils.nullSafeEquals(this.factoryMethodName, that.factoryMethodName);
|
||||
rtn = rtn &= ObjectUtils.nullSafeEquals(this.initMethodName, that.initMethodName);
|
||||
rtn = rtn &= this.enforceInitMethod == that.enforceInitMethod;
|
||||
rtn = rtn &= ObjectUtils.nullSafeEquals(this.destroyMethodName, that.destroyMethodName);
|
||||
rtn = rtn &= this.enforceDestroyMethod == that.enforceDestroyMethod;
|
||||
rtn = rtn &= this.synthetic == that.synthetic;
|
||||
rtn = rtn &= this.role == that.role;
|
||||
return rtn && super.equals(other);
|
||||
return (ObjectUtils.nullSafeEquals(getBeanClassName(), that.getBeanClassName()) &&
|
||||
ObjectUtils.nullSafeEquals(this.scope, that.scope) &&
|
||||
this.abstractFlag == that.abstractFlag &&
|
||||
this.lazyInit == that.lazyInit &&
|
||||
this.autowireMode == that.autowireMode &&
|
||||
this.dependencyCheck == that.dependencyCheck &&
|
||||
Arrays.equals(this.dependsOn, that.dependsOn) &&
|
||||
this.autowireCandidate == that.autowireCandidate &&
|
||||
ObjectUtils.nullSafeEquals(this.qualifiers, that.qualifiers) &&
|
||||
this.primary == that.primary &&
|
||||
this.nonPublicAccessAllowed == that.nonPublicAccessAllowed &&
|
||||
this.lenientConstructorResolution == that.lenientConstructorResolution &&
|
||||
ObjectUtils.nullSafeEquals(this.constructorArgumentValues, that.constructorArgumentValues) &&
|
||||
ObjectUtils.nullSafeEquals(this.propertyValues, that.propertyValues) &&
|
||||
ObjectUtils.nullSafeEquals(this.methodOverrides, that.methodOverrides) &&
|
||||
ObjectUtils.nullSafeEquals(this.factoryBeanName, that.factoryBeanName) &&
|
||||
ObjectUtils.nullSafeEquals(this.factoryMethodName, that.factoryMethodName) &&
|
||||
ObjectUtils.nullSafeEquals(this.initMethodName, that.initMethodName) &&
|
||||
this.enforceInitMethod == that.enforceInitMethod &&
|
||||
ObjectUtils.nullSafeEquals(this.destroyMethodName, that.destroyMethodName) &&
|
||||
this.enforceDestroyMethod == that.enforceDestroyMethod &&
|
||||
this.synthetic == that.synthetic &&
|
||||
this.role == that.role &&
|
||||
super.equals(other));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -887,7 +887,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
|
||||
/**
|
||||
* Return whether this factory holds a InstantiationAwareBeanPostProcessor
|
||||
* that will get applied to singleton beans on shutdown.
|
||||
* that will get applied to singleton beans on creation.
|
||||
* @see #addBeanPostProcessor
|
||||
* @see org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
|
||||
*/
|
||||
@@ -1283,7 +1283,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
else {
|
||||
throw new NoSuchBeanDefinitionException(parentBeanName,
|
||||
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
|
||||
"': cannot be resolved without an AbstractBeanFactory parent");
|
||||
"': cannot be resolved without a ConfigurableBeanFactory parent");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1298,7 +1298,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
|
||||
// Set default singleton scope, if not configured before.
|
||||
if (!StringUtils.hasLength(mbd.getScope())) {
|
||||
mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
|
||||
mbd.setScope(SCOPE_SINGLETON);
|
||||
}
|
||||
|
||||
// A bean contained in a non-singleton bean cannot be a singleton itself.
|
||||
|
||||
+9
@@ -302,6 +302,15 @@ public final class BeanDefinitionBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this bean is a primary autowire candidate.
|
||||
* @since 5.1.11
|
||||
*/
|
||||
public BeanDefinitionBuilder setPrimary(boolean primary) {
|
||||
this.beanDefinition.setPrimary(primary);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the role of this definition.
|
||||
*/
|
||||
|
||||
+18
-2
@@ -162,6 +162,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
/** Map of bean definition objects, keyed by bean name. */
|
||||
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
|
||||
|
||||
/** Map from bean name to merged BeanDefinitionHolder. */
|
||||
private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders = new ConcurrentHashMap<>(256);
|
||||
|
||||
/** Map of singleton and non-singleton bean names, keyed by dependency type. */
|
||||
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
|
||||
|
||||
@@ -759,8 +762,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (mbd.isFactoryMethodUnique && mbd.factoryMethodToIntrospect == null) {
|
||||
new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
|
||||
}
|
||||
return resolver.isAutowireCandidate(
|
||||
new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName)), descriptor);
|
||||
BeanDefinitionHolder holder = (beanName.equals(beanDefinitionName) ?
|
||||
this.mergedBeanDefinitionHolders.computeIfAbsent(beanName,
|
||||
key -> new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName))) :
|
||||
new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName)));
|
||||
return resolver.isAutowireCandidate(holder, descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -783,9 +789,16 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
return iterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearMergedBeanDefinition(String beanName) {
|
||||
super.clearMergedBeanDefinition(beanName);
|
||||
this.mergedBeanDefinitionHolders.remove(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearMetadataCache() {
|
||||
super.clearMetadataCache();
|
||||
this.mergedBeanDefinitionHolders.clear();
|
||||
clearByTypeCache();
|
||||
}
|
||||
|
||||
@@ -942,6 +955,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (existingDefinition != null || containsSingleton(beanName)) {
|
||||
resetBeanDefinition(beanName);
|
||||
}
|
||||
else if (isConfigurationFrozen()) {
|
||||
clearByTypeCache();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+13
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -70,6 +70,10 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
|
||||
|
||||
/** Maximum number of suppressed exceptions to preserve. */
|
||||
private static final int SUPPRESSED_EXCEPTIONS_LIMIT = 100;
|
||||
|
||||
|
||||
/** Cache of singleton objects: bean name to bean instance. */
|
||||
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
|
||||
|
||||
@@ -90,7 +94,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
private final Set<String> inCreationCheckExclusions =
|
||||
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
|
||||
|
||||
/** List of suppressed Exceptions, available for associating related causes. */
|
||||
/** Collection of suppressed Exceptions, available for associating related causes. */
|
||||
@Nullable
|
||||
private Set<Exception> suppressedExceptions;
|
||||
|
||||
@@ -253,13 +257,17 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an Exception that happened to get suppressed during the creation of a
|
||||
* Register an exception that happened to get suppressed during the creation of a
|
||||
* singleton bean instance, e.g. a temporary circular reference resolution problem.
|
||||
* <p>The default implementation preserves any given exception in this registry's
|
||||
* collection of suppressed exceptions, up to a limit of 100 exceptions, adding
|
||||
* them as related causes to an eventual top-level {@link BeanCreationException}.
|
||||
* @param ex the Exception to register
|
||||
* @see BeanCreationException#getRelatedCauses()
|
||||
*/
|
||||
protected void onSuppressedException(Exception ex) {
|
||||
synchronized (this.singletonObjects) {
|
||||
if (this.suppressedExceptions != null) {
|
||||
if (this.suppressedExceptions != null && this.suppressedExceptions.size() < SUPPRESSED_EXCEPTIONS_LIMIT) {
|
||||
this.suppressedExceptions.add(ex);
|
||||
}
|
||||
}
|
||||
@@ -612,6 +620,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
* should <i>not</i> have their own mutexes involved in singleton creation,
|
||||
* to avoid the potential for deadlocks in lazy-init situations.
|
||||
*/
|
||||
@Override
|
||||
public final Object getSingletonMutex() {
|
||||
return this.singletonObjects;
|
||||
}
|
||||
|
||||
+3
-3
@@ -311,9 +311,9 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
* assuming a "force" parameter), else logging an error.
|
||||
*/
|
||||
private void invokeCustomDestroyMethod(final Method destroyMethod) {
|
||||
Class<?>[] paramTypes = destroyMethod.getParameterTypes();
|
||||
final Object[] args = new Object[paramTypes.length];
|
||||
if (paramTypes.length == 1) {
|
||||
int paramCount = destroyMethod.getParameterCount();
|
||||
final Object[] args = new Object[paramCount];
|
||||
if (paramCount == 1) {
|
||||
args[0] = Boolean.TRUE;
|
||||
}
|
||||
if (logger.isTraceEnabled()) {
|
||||
|
||||
+6
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -40,6 +40,11 @@ public class SimpleAutowireCandidateResolver implements AutowireCandidateResolve
|
||||
return descriptor.isRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasQualifier(DependencyDescriptor descriptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object getSuggestedValue(DependencyDescriptor descriptor) {
|
||||
|
||||
+4
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -146,8 +146,9 @@ public class ArgumentConvertingMethodInvoker extends MethodInvoker {
|
||||
for (Method candidate : candidates) {
|
||||
if (candidate.getName().equals(targetMethod)) {
|
||||
// Check if the inspected method has the correct number of parameters.
|
||||
Class<?>[] paramTypes = candidate.getParameterTypes();
|
||||
if (paramTypes.length == argCount) {
|
||||
int parameterCount = candidate.getParameterCount();
|
||||
if (parameterCount == argCount) {
|
||||
Class<?>[] paramTypes = candidate.getParameterTypes();
|
||||
Object[] convertedArguments = new Object[argCount];
|
||||
boolean match = true;
|
||||
for (int j = 0; j < argCount && match; j++) {
|
||||
|
||||
+33
@@ -1399,6 +1399,39 @@ public class DefaultListableBeanFactoryTests {
|
||||
lbf.getBean(TestBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanByTypeWithLateRegistration() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
try {
|
||||
lbf.getBean(TestBean.class);
|
||||
fail("Should have thrown NoSuchBeanDefinitionException");
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("bd1", bd1);
|
||||
TestBean bean = lbf.getBean(TestBean.class);
|
||||
assertThat(bean.getBeanName(), equalTo("bd1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanByTypeWithLateRegistrationAgainstFrozen() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
lbf.freezeConfiguration();
|
||||
try {
|
||||
lbf.getBean(TestBean.class);
|
||||
fail("Should have thrown NoSuchBeanDefinitionException");
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("bd1", bd1);
|
||||
TestBean bean = lbf.getBean(TestBean.class);
|
||||
assertThat(bean.getBeanName(), equalTo("bd1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanByTypeDefinedInParent() {
|
||||
DefaultListableBeanFactory parent = new DefaultListableBeanFactory();
|
||||
|
||||
+56
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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,15 @@
|
||||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.yaml.snakeyaml.constructor.ConstructorException;
|
||||
import org.yaml.snakeyaml.parser.ParserException;
|
||||
import org.yaml.snakeyaml.scanner.ScannerException;
|
||||
|
||||
@@ -34,6 +37,7 @@ import static org.junit.Assert.*;
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public class YamlProcessorTests {
|
||||
|
||||
@@ -45,7 +49,7 @@ public class YamlProcessorTests {
|
||||
|
||||
@Test
|
||||
public void arrayConvertedToIndexedBeanReference() {
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar: [1,2,3]".getBytes()));
|
||||
setYaml("foo: bar\nbar: [1,2,3]");
|
||||
this.processor.process((properties, map) -> {
|
||||
assertEquals(4, properties.size());
|
||||
assertEquals("bar", properties.get("foo"));
|
||||
@@ -61,13 +65,13 @@ public class YamlProcessorTests {
|
||||
|
||||
@Test
|
||||
public void testStringResource() {
|
||||
this.processor.setResources(new ByteArrayResource("foo # a document that is a literal".getBytes()));
|
||||
setYaml("foo # a document that is a literal");
|
||||
this.processor.process((properties, map) -> assertEquals("foo", map.get("document")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadDocumentStart() {
|
||||
this.processor.setResources(new ByteArrayResource("foo # a document\nbar: baz".getBytes()));
|
||||
setYaml("foo # a document\nbar: baz");
|
||||
this.exception.expect(ParserException.class);
|
||||
this.exception.expectMessage("line 2, column 1");
|
||||
this.processor.process((properties, map) -> {});
|
||||
@@ -75,7 +79,7 @@ public class YamlProcessorTests {
|
||||
|
||||
@Test
|
||||
public void testBadResource() {
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\ncd\nspam:\n foo: baz".getBytes()));
|
||||
setYaml("foo: bar\ncd\nspam:\n foo: baz");
|
||||
this.exception.expect(ScannerException.class);
|
||||
this.exception.expectMessage("line 3, column 1");
|
||||
this.processor.process((properties, map) -> {});
|
||||
@@ -83,7 +87,7 @@ public class YamlProcessorTests {
|
||||
|
||||
@Test
|
||||
public void mapConvertedToIndexedBeanReference() {
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar:\n spam: bucket".getBytes()));
|
||||
setYaml("foo: bar\nbar:\n spam: bucket");
|
||||
this.processor.process((properties, map) -> {
|
||||
assertEquals("bucket", properties.get("bar.spam"));
|
||||
assertEquals(2, properties.size());
|
||||
@@ -92,7 +96,7 @@ public class YamlProcessorTests {
|
||||
|
||||
@Test
|
||||
public void integerKeyBehaves() {
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\n1: bar".getBytes()));
|
||||
setYaml("foo: bar\n1: bar");
|
||||
this.processor.process((properties, map) -> {
|
||||
assertEquals("bar", properties.get("[1]"));
|
||||
assertEquals(2, properties.size());
|
||||
@@ -101,7 +105,7 @@ public class YamlProcessorTests {
|
||||
|
||||
@Test
|
||||
public void integerDeepKeyBehaves() {
|
||||
this.processor.setResources(new ByteArrayResource("foo:\n 1: bar".getBytes()));
|
||||
setYaml("foo:\n 1: bar");
|
||||
this.processor.process((properties, map) -> {
|
||||
assertEquals("bar", properties.get("foo[1]"));
|
||||
assertEquals(1, properties.size());
|
||||
@@ -111,7 +115,7 @@ public class YamlProcessorTests {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void flattenedMapIsSameAsPropertiesButOrdered() {
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar:\n spam: bucket".getBytes()));
|
||||
setYaml("foo: bar\nbar:\n spam: bucket");
|
||||
this.processor.process((properties, map) -> {
|
||||
assertEquals("bucket", properties.get("bar.spam"));
|
||||
assertEquals(2, properties.size());
|
||||
@@ -124,4 +128,47 @@ public class YamlProcessorTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customTypeSupportedByDefault() throws Exception {
|
||||
URL url = new URL("https://localhost:9000/");
|
||||
setYaml("value: !!java.net.URL [\"" + url + "\"]");
|
||||
|
||||
this.processor.process((properties, map) -> {
|
||||
assertEquals(1, properties.size());
|
||||
assertEquals(1, map.size());
|
||||
assertEquals(url, properties.get("value"));
|
||||
assertEquals(url, map.get("value"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customTypesSupportedDueToExplicitConfiguration() throws Exception {
|
||||
this.processor.setSupportedTypes(URL.class, String.class);
|
||||
|
||||
URL url = new URL("https://localhost:9000/");
|
||||
setYaml("value: !!java.net.URL [!!java.lang.String [\"" + url + "\"]]");
|
||||
|
||||
this.processor.process((properties, map) -> {
|
||||
assertEquals(1, properties.size());
|
||||
assertEquals(1, map.size());
|
||||
assertEquals(url, properties.get("value"));
|
||||
assertEquals(url, map.get("value"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customTypeNotSupportedDueToExplicitConfiguration() {
|
||||
this.processor.setSupportedTypes(List.class);
|
||||
|
||||
setYaml("value: !!java.net.URL [\"https://localhost:9000/\"]");
|
||||
|
||||
this.exception.expect(ConstructorException.class);
|
||||
this.exception.expectMessage("Unsupported type encountered in YAML document: java.net.URL");
|
||||
this.processor.process((properties, map) -> {});
|
||||
}
|
||||
|
||||
private void setYaml(String yaml) {
|
||||
this.processor.setResources(new ByteArrayResource(yaml.getBytes()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ dependencies {
|
||||
optional("org.freemarker:freemarker:${freemarkerVersion}")
|
||||
testCompile(project(":spring-context"))
|
||||
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
testCompile("org.hibernate:hibernate-validator:6.0.17.Final")
|
||||
testCompile("org.hibernate:hibernate-validator:6.0.20.Final")
|
||||
testCompile("javax.annotation:javax.annotation-api:1.3.2")
|
||||
testRuntime("org.ehcache:jcache:1.0.1")
|
||||
testRuntime("org.ehcache:ehcache:3.4.0")
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -35,6 +35,7 @@ import org.springframework.util.Assert;
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.3
|
||||
* @see CaffeineCacheManager
|
||||
*/
|
||||
public class CaffeineCache extends AbstractValueAdaptingCache {
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -34,6 +34,7 @@ import org.springframework.util.Assert;
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @since 3.1
|
||||
* @see EhCacheCacheManager
|
||||
*/
|
||||
public class EhCacheCache implements Cache {
|
||||
|
||||
@@ -95,7 +96,6 @@ public class EhCacheCache implements Cache {
|
||||
this.cache.releaseWriteLockOnKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private <T> T loadValue(Object key, Callable<T> valueLoader) {
|
||||
|
||||
Vendored
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -34,6 +34,7 @@ import org.springframework.util.Assert;
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @since 3.1
|
||||
* @see EhCacheCache
|
||||
*/
|
||||
public class EhCacheCacheManager extends AbstractTransactionSupportingCacheManager {
|
||||
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -36,6 +36,7 @@ import org.springframework.util.Assert;
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @since 3.2
|
||||
* @see JCacheCacheManager
|
||||
*/
|
||||
public class JCacheCache extends AbstractValueAdaptingCache {
|
||||
|
||||
|
||||
Vendored
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -36,6 +36,7 @@ import org.springframework.util.Assert;
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @since 3.2
|
||||
* @see JCacheCache
|
||||
*/
|
||||
public class JCacheCacheManager extends AbstractTransactionSupportingCacheManager {
|
||||
|
||||
|
||||
+1
@@ -88,6 +88,7 @@ public class JCacheAspectSupport extends AbstractCacheInvoker implements Initial
|
||||
return this.cacheOperationSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
getCacheOperationSource();
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -110,7 +110,7 @@ public class LocalDataSourceJobStore extends JobStoreCMT {
|
||||
public void shutdown() {
|
||||
// Do nothing - a Spring-managed DataSource has its own lifecycle.
|
||||
}
|
||||
/* Quartz 2.2 initialize method */
|
||||
@Override
|
||||
public void initialize() {
|
||||
// Do nothing - a Spring-managed DataSource has its own lifecycle.
|
||||
}
|
||||
@@ -138,7 +138,7 @@ public class LocalDataSourceJobStore extends JobStoreCMT {
|
||||
public void shutdown() {
|
||||
// Do nothing - a Spring-managed DataSource has its own lifecycle.
|
||||
}
|
||||
/* Quartz 2.2 initialize method */
|
||||
@Override
|
||||
public void initialize() {
|
||||
// Do nothing - a Spring-managed DataSource has its own lifecycle.
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -82,6 +82,7 @@ public class ResourceLoaderClassLoadHelper implements ClassLoadHelper {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> Class<? extends T> loadClass(String name, Class<T> clazz) throws ClassNotFoundException {
|
||||
return (Class<? extends T>) loadClass(name);
|
||||
}
|
||||
|
||||
@@ -18,17 +18,17 @@ dependencies {
|
||||
optional("javax.xml.ws:jaxws-api:2.3.1")
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.codehaus.groovy:groovy:${groovyVersion}")
|
||||
optional("org.beanshell:bsh:2.0b5")
|
||||
optional("joda-time:joda-time:2.10.4")
|
||||
optional("org.apache-extras.beanshell:bsh:2.0b6")
|
||||
optional("joda-time:joda-time:2.10.5")
|
||||
optional("org.hibernate:hibernate-validator:5.4.3.Final")
|
||||
optional("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
|
||||
optional("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}")
|
||||
testCompile("org.codehaus.groovy:groovy-jsr223:${groovyVersion}")
|
||||
testCompile("org.codehaus.groovy:groovy-test:${groovyVersion}")
|
||||
testCompile("org.codehaus.groovy:groovy-xml:${groovyVersion}")
|
||||
testCompile("org.apache.commons:commons-pool2:2.6.0")
|
||||
testCompile("org.apache.commons:commons-pool2:2.6.2")
|
||||
testCompile("javax.inject:javax.inject-tck:1")
|
||||
testCompile("org.awaitility:awaitility:3.1.3")
|
||||
testCompile("org.awaitility:awaitility:3.1.6")
|
||||
testRuntime("javax.xml.bind:jaxb-api:2.3.1")
|
||||
testRuntime("org.glassfish:javax.el:3.0.1-b08")
|
||||
testRuntime("org.javamoney:moneta:1.3")
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -191,7 +191,7 @@ public class ConcurrentMapCache extends AbstractValueAdaptingCache {
|
||||
}
|
||||
|
||||
private Object serializeValue(SerializationDelegate serialization, Object storeValue) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
|
||||
try {
|
||||
serialization.serialize(storeValue, out);
|
||||
return out.toByteArray();
|
||||
|
||||
Vendored
+2
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -190,9 +190,7 @@ public class ConcurrentMapCacheManager implements CacheManager, BeanClassLoaderA
|
||||
*/
|
||||
protected Cache createConcurrentMapCache(String name) {
|
||||
SerializationDelegate actualSerialization = (isStoreByValue() ? this.serialization : null);
|
||||
return new ConcurrentMapCache(name, new ConcurrentHashMap<>(256),
|
||||
isAllowNullValues(), actualSerialization);
|
||||
|
||||
return new ConcurrentMapCache(name, new ConcurrentHashMap<>(256), isAllowNullValues(), actualSerialization);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -52,6 +52,7 @@ import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.function.SingletonSupplier;
|
||||
import org.springframework.util.function.SupplierUtils;
|
||||
@@ -381,9 +382,9 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
|
||||
return wrapCacheValue(method, cache.get(key, () -> unwrapReturnValue(invokeOperation(invoker))));
|
||||
}
|
||||
catch (Cache.ValueRetrievalException ex) {
|
||||
// The invoker wraps any Throwable in a ThrowableWrapper instance so we
|
||||
// can just make sure that one bubbles up the stack.
|
||||
throw (CacheOperationInvoker.ThrowableWrapper) ex.getCause();
|
||||
// Directly propagate ThrowableWrapper from the invoker,
|
||||
// or potentially also an IllegalArgumentException etc.
|
||||
ReflectionUtils.rethrowRuntimeException(ex.getCause());
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
+3
-1
@@ -32,7 +32,9 @@ import org.springframework.util.StringUtils;
|
||||
@SuppressWarnings("serial")
|
||||
public class SimpleKey implements Serializable {
|
||||
|
||||
/** An empty key. */
|
||||
/**
|
||||
* An empty key.
|
||||
*/
|
||||
public static final SimpleKey EMPTY = new SimpleKey();
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -30,6 +30,7 @@ import org.springframework.util.Assert;
|
||||
* @author Costin Leau
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.3.4
|
||||
* @see NoOpCacheManager
|
||||
*/
|
||||
public class NoOpCache implements Cache {
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -37,7 +37,7 @@ import org.springframework.lang.Nullable;
|
||||
* @author Costin Leau
|
||||
* @author Stephane Nicoll
|
||||
* @since 3.1
|
||||
* @see CompositeCacheManager
|
||||
* @see NoOpCache
|
||||
*/
|
||||
public class NoOpCacheManager implements CacheManager {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -17,19 +17,21 @@
|
||||
package org.springframework.context;
|
||||
|
||||
/**
|
||||
* An extension of the {@link Lifecycle} interface for those objects that require to
|
||||
* be started upon ApplicationContext refresh and/or shutdown in a particular order.
|
||||
* The {@link #isAutoStartup()} return value indicates whether this object should
|
||||
* An extension of the {@link Lifecycle} interface for those objects that require
|
||||
* to be started upon {@code ApplicationContext} refresh and/or shutdown in a
|
||||
* particular order.
|
||||
*
|
||||
* <p>The {@link #isAutoStartup()} return value indicates whether this object should
|
||||
* be started at the time of a context refresh. The callback-accepting
|
||||
* {@link #stop(Runnable)} method is useful for objects that have an asynchronous
|
||||
* shutdown process. Any implementation of this interface <i>must</i> invoke the
|
||||
* callback's {@code run()} method upon shutdown completion to avoid unnecessary
|
||||
* delays in the overall ApplicationContext shutdown.
|
||||
* delays in the overall {@code ApplicationContext} shutdown.
|
||||
*
|
||||
* <p>This interface extends {@link Phased}, and the {@link #getPhase()} method's
|
||||
* return value indicates the phase within which this Lifecycle component should
|
||||
* be started and stopped. The startup process begins with the <i>lowest</i> phase
|
||||
* value and ends with the <i>highest</i> phase value ({@code Integer.MIN_VALUE}
|
||||
* return value indicates the phase within which this {@code Lifecycle} component
|
||||
* should be started and stopped. The startup process begins with the <i>lowest</i>
|
||||
* phase value and ends with the <i>highest</i> phase value ({@code Integer.MIN_VALUE}
|
||||
* is the lowest possible, and {@code Integer.MAX_VALUE} is the highest possible).
|
||||
* The shutdown process will apply the reverse order. Any components with the
|
||||
* same value will be arbitrarily ordered within the same phase.
|
||||
@@ -44,9 +46,11 @@ package org.springframework.context;
|
||||
*
|
||||
* <p>Any {@code Lifecycle} components within the context that do not also
|
||||
* implement {@code SmartLifecycle} will be treated as if they have a phase
|
||||
* value of 0. That way a {@code SmartLifecycle} implementation may start
|
||||
* before those {@code Lifecycle} components if it has a negative phase value,
|
||||
* or it may start after those components if it has a positive phase value.
|
||||
* value of {@code 0}. This allows a {@code SmartLifecycle} component to start
|
||||
* before those {@code Lifecycle} components if the {@code SmartLifecycle}
|
||||
* component has a negative phase value, or the {@code SmartLifecycle} component
|
||||
* may start after those {@code Lifecycle} components if the {@code SmartLifecycle}
|
||||
* component has a positive phase value.
|
||||
*
|
||||
* <p>Note that, due to the auto-startup support in {@code SmartLifecycle}, a
|
||||
* {@code SmartLifecycle} bean instance will usually get initialized on startup
|
||||
@@ -55,6 +59,7 @@ package org.springframework.context;
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 3.0
|
||||
* @see LifecycleProcessor
|
||||
* @see ConfigurableApplicationContext
|
||||
@@ -63,9 +68,10 @@ public interface SmartLifecycle extends Lifecycle, Phased {
|
||||
|
||||
/**
|
||||
* The default phase for {@code SmartLifecycle}: {@code Integer.MAX_VALUE}.
|
||||
* <p>This is different from the common phase 0 associated with regular
|
||||
* <p>This is different from the common phase {@code 0} associated with regular
|
||||
* {@link Lifecycle} implementations, putting the typically auto-started
|
||||
* {@code SmartLifecycle} beans into a separate later shutdown phase.
|
||||
* {@code SmartLifecycle} beans into a later startup phase and an earlier
|
||||
* shutdown phase.
|
||||
* @since 5.1
|
||||
* @see #getPhase()
|
||||
* @see org.springframework.context.support.DefaultLifecycleProcessor#getPhase(Lifecycle)
|
||||
@@ -115,7 +121,8 @@ public interface SmartLifecycle extends Lifecycle, Phased {
|
||||
/**
|
||||
* Return the phase that this lifecycle object is supposed to run in.
|
||||
* <p>The default implementation returns {@link #DEFAULT_PHASE} in order to
|
||||
* let stop callbacks execute after regular {@code Lifecycle} implementations.
|
||||
* let {@code stop()} callbacks execute after regular {@code Lifecycle}
|
||||
* implementations.
|
||||
* @see #isAutoStartup()
|
||||
* @see #start()
|
||||
* @see #stop(Runnable)
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -33,7 +33,8 @@ import org.springframework.core.type.AnnotationMetadata;
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
* @see EnableAspectJAutoProxy
|
||||
* @see org.springframework.cache.annotation.EnableCaching
|
||||
* @see org.springframework.transaction.annotation.EnableTransactionManagement
|
||||
*/
|
||||
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -29,7 +29,6 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
|
||||
import org.springframework.beans.factory.annotation.Lookup;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
@@ -386,8 +385,8 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC
|
||||
for (String type : types) {
|
||||
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(type);
|
||||
if (isCandidateComponent(metadataReader)) {
|
||||
AnnotatedGenericBeanDefinition sbd = new AnnotatedGenericBeanDefinition(
|
||||
metadataReader.getAnnotationMetadata());
|
||||
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
|
||||
sbd.setSource(metadataReader.getResource());
|
||||
if (isCandidateComponent(sbd)) {
|
||||
if (debugEnabled) {
|
||||
logger.debug("Using candidate component class from index: " + type);
|
||||
@@ -430,7 +429,6 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC
|
||||
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
|
||||
if (isCandidateComponent(metadataReader)) {
|
||||
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
|
||||
sbd.setResource(resource);
|
||||
sbd.setSource(resource);
|
||||
if (isCandidateComponent(sbd)) {
|
||||
if (debugEnabled) {
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -344,9 +344,9 @@ import org.springframework.stereotype.Component;
|
||||
*
|
||||
* <p>By default, {@code @Bean} methods will be <em>eagerly instantiated</em> at container
|
||||
* bootstrap time. To avoid this, {@code @Configuration} may be used in conjunction with
|
||||
* the {@link Lazy @Lazy} annotation to indicate that all {@code @Bean} methods declared within
|
||||
* the class are by default lazily initialized. Note that {@code @Lazy} may be used on
|
||||
* individual {@code @Bean} methods as well.
|
||||
* the {@link Lazy @Lazy} annotation to indicate that all {@code @Bean} methods declared
|
||||
* within the class are by default lazily initialized. Note that {@code @Lazy} may be used
|
||||
* on individual {@code @Bean} methods as well.
|
||||
*
|
||||
* <h2>Testing support for {@code @Configuration} classes</h2>
|
||||
*
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -209,7 +209,6 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
}
|
||||
|
||||
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
|
||||
beanDef.setResource(configClass.getResource());
|
||||
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
|
||||
|
||||
if (metadata.isStatic()) {
|
||||
@@ -381,6 +380,7 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
public ConfigurationClassBeanDefinition(ConfigurationClass configClass, MethodMetadata beanMethodMetadata) {
|
||||
this.annotationMetadata = configClass.getMetadata();
|
||||
this.factoryMethodMetadata = beanMethodMetadata;
|
||||
setResource(configClass.getResource());
|
||||
setLenientConstructorResolution(false);
|
||||
}
|
||||
|
||||
|
||||
+5
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -748,8 +748,7 @@ class ConfigurationClassParser {
|
||||
* @param importSelector the selector to handle
|
||||
*/
|
||||
public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
|
||||
DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(
|
||||
configClass, importSelector);
|
||||
DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
|
||||
if (this.deferredImportSelectors == null) {
|
||||
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
|
||||
handler.register(holder);
|
||||
@@ -775,7 +774,6 @@ class ConfigurationClassParser {
|
||||
this.deferredImportSelectors = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -786,8 +784,7 @@ class ConfigurationClassParser {
|
||||
private final Map<AnnotationMetadata, ConfigurationClass> configurationClasses = new HashMap<>();
|
||||
|
||||
public void register(DeferredImportSelectorHolder deferredImport) {
|
||||
Class<? extends Group> group = deferredImport.getImportSelector()
|
||||
.getImportGroup();
|
||||
Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
|
||||
DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
|
||||
(group != null ? group : deferredImport),
|
||||
key -> new DeferredImportSelectorGrouping(createGroup(group)));
|
||||
@@ -799,8 +796,7 @@ class ConfigurationClassParser {
|
||||
public void processGroupImports() {
|
||||
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
|
||||
grouping.getImports().forEach(entry -> {
|
||||
ConfigurationClass configurationClass = this.configurationClasses.get(
|
||||
entry.getMetadata());
|
||||
ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
|
||||
try {
|
||||
processImports(configurationClass, asSourceClass(configurationClass),
|
||||
asSourceClasses(entry.getImportClassName()), false);
|
||||
@@ -818,8 +814,7 @@ class ConfigurationClassParser {
|
||||
}
|
||||
|
||||
private Group createGroup(@Nullable Class<? extends Group> type) {
|
||||
Class<? extends Group> effectiveType = (type != null ? type
|
||||
: DefaultDeferredImportSelectorGroup.class);
|
||||
Class<? extends Group> effectiveType = (type != null ? type : DefaultDeferredImportSelectorGroup.class);
|
||||
Group group = BeanUtils.instantiateClass(effectiveType);
|
||||
ParserStrategyUtils.invokeAwareMethods(group,
|
||||
ConfigurationClassParser.this.environment,
|
||||
@@ -827,7 +822,6 @@ class ConfigurationClassParser {
|
||||
ConfigurationClassParser.this.registry);
|
||||
return group;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+10
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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,8 +16,6 @@
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
@@ -53,6 +51,7 @@ public interface DeferredImportSelector extends ImportSelector {
|
||||
|
||||
/**
|
||||
* Interface used to group results from different import selectors.
|
||||
* @since 5.0
|
||||
*/
|
||||
interface Group {
|
||||
|
||||
@@ -100,7 +99,7 @@ public interface DeferredImportSelector extends ImportSelector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
public boolean equals(@Nullable Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
@@ -108,13 +107,17 @@ public interface DeferredImportSelector extends ImportSelector {
|
||||
return false;
|
||||
}
|
||||
Entry entry = (Entry) other;
|
||||
return (Objects.equals(this.metadata, entry.metadata) &&
|
||||
Objects.equals(this.importClassName, entry.importClassName));
|
||||
return (this.metadata.equals(entry.metadata) && this.importClassName.equals(entry.importClassName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.metadata, this.importClassName);
|
||||
return (this.metadata.hashCode() * 31 + this.importClassName.hashCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.importClassName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -50,6 +50,7 @@ public interface ImportSelector {
|
||||
/**
|
||||
* Select and return the names of which class(es) should be imported based on
|
||||
* the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
|
||||
* @return the class names, or an empty array if none
|
||||
*/
|
||||
String[] selectImports(AnnotationMetadata importingClassMetadata);
|
||||
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -42,6 +42,7 @@ import org.springframework.util.Assert;
|
||||
* @see ConfigurableApplicationContext#LOAD_TIME_WEAVER_BEAN_NAME
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class LoadTimeWeavingConfiguration implements ImportAware, BeanClassLoaderAware {
|
||||
|
||||
@Nullable
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -50,6 +50,7 @@ import org.springframework.util.StringUtils;
|
||||
* @see EnableMBeanExport
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class MBeanExportConfiguration implements ImportAware, EnvironmentAware, BeanFactoryAware {
|
||||
|
||||
private static final String MBEAN_EXPORTER_BEAN_NAME = "mbeanExporter";
|
||||
|
||||
+6
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -170,8 +170,11 @@ import org.springframework.core.io.support.PropertySourceFactory;
|
||||
public @interface PropertySource {
|
||||
|
||||
/**
|
||||
* Indicate the name of this property source. If omitted, a name will
|
||||
* be generated based on the description of the underlying resource.
|
||||
* Indicate the name of this property source. If omitted, the {@link #factory()}
|
||||
* will generate a name based on the underlying resource (in the case of
|
||||
* {@link org.springframework.core.io.support.DefaultPropertySourceFactory}:
|
||||
* derived from the resource description through a corresponding name-less
|
||||
* {@link org.springframework.core.io.support.ResourcePropertySource} constructor).
|
||||
* @see org.springframework.core.env.PropertySource#getName()
|
||||
* @see org.springframework.core.io.Resource#getDescription()
|
||||
*/
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -60,6 +60,7 @@ public class ScannedGenericBeanDefinition extends GenericBeanDefinition implemen
|
||||
Assert.notNull(metadataReader, "MetadataReader must not be null");
|
||||
this.metadata = metadataReader.getAnnotationMetadata();
|
||||
setBeanClassName(this.metadata.getClassName());
|
||||
setResource(metadataReader.getResource());
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -53,6 +53,6 @@ public enum ScopedProxyMode {
|
||||
/**
|
||||
* Create a class-based proxy (uses CGLIB).
|
||||
*/
|
||||
TARGET_CLASS;
|
||||
TARGET_CLASS
|
||||
|
||||
}
|
||||
|
||||
+16
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -57,6 +57,19 @@ public class CandidateComponentsIndex {
|
||||
this.index = parseIndex(content);
|
||||
}
|
||||
|
||||
private static MultiValueMap<String, Entry> parseIndex(List<Properties> content) {
|
||||
MultiValueMap<String, Entry> index = new LinkedMultiValueMap<>();
|
||||
for (Properties entry : content) {
|
||||
entry.forEach((type, values) -> {
|
||||
String[] stereotypes = ((String) values).split(",");
|
||||
for (String stereotype : stereotypes) {
|
||||
index.add(stereotype, new Entry((String) type));
|
||||
}
|
||||
});
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the candidate types that are associated with the specified stereotype.
|
||||
@@ -76,21 +89,11 @@ public class CandidateComponentsIndex {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
private static MultiValueMap<String, Entry> parseIndex(List<Properties> content) {
|
||||
MultiValueMap<String, Entry> index = new LinkedMultiValueMap<>();
|
||||
for (Properties entry : content) {
|
||||
entry.forEach((type, values) -> {
|
||||
String[] stereotypes = ((String) values).split(",");
|
||||
for (String stereotype : stereotypes) {
|
||||
index.add(stereotype, new Entry((String) type));
|
||||
}
|
||||
});
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
private static class Entry {
|
||||
|
||||
private final String type;
|
||||
|
||||
private final String packageName;
|
||||
|
||||
Entry(String type) {
|
||||
@@ -106,7 +109,6 @@ public class CandidateComponentsIndex {
|
||||
return this.type.startsWith(basePackage);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -79,6 +79,7 @@ import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
@@ -835,7 +836,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
// Publish early application events now that we finally have a multicaster...
|
||||
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
|
||||
this.earlyApplicationEvents = null;
|
||||
if (earlyEventsToProcess != null) {
|
||||
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
|
||||
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
|
||||
getApplicationEventMulticaster().multicastEvent(earlyEvent);
|
||||
}
|
||||
|
||||
+16
-26
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -72,10 +72,7 @@ public abstract class AbstractRefreshableApplicationContext extends AbstractAppl
|
||||
|
||||
/** Bean factory for this context. */
|
||||
@Nullable
|
||||
private DefaultListableBeanFactory beanFactory;
|
||||
|
||||
/** Synchronization monitor for the internal BeanFactory. */
|
||||
private final Object beanFactoryMonitor = new Object();
|
||||
private volatile DefaultListableBeanFactory beanFactory;
|
||||
|
||||
|
||||
/**
|
||||
@@ -131,9 +128,7 @@ public abstract class AbstractRefreshableApplicationContext extends AbstractAppl
|
||||
beanFactory.setSerializationId(getId());
|
||||
customizeBeanFactory(beanFactory);
|
||||
loadBeanDefinitions(beanFactory);
|
||||
synchronized (this.beanFactoryMonitor) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
|
||||
@@ -142,21 +137,19 @@ public abstract class AbstractRefreshableApplicationContext extends AbstractAppl
|
||||
|
||||
@Override
|
||||
protected void cancelRefresh(BeansException ex) {
|
||||
synchronized (this.beanFactoryMonitor) {
|
||||
if (this.beanFactory != null) {
|
||||
this.beanFactory.setSerializationId(null);
|
||||
}
|
||||
DefaultListableBeanFactory beanFactory = this.beanFactory;
|
||||
if (beanFactory != null) {
|
||||
beanFactory.setSerializationId(null);
|
||||
}
|
||||
super.cancelRefresh(ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void closeBeanFactory() {
|
||||
synchronized (this.beanFactoryMonitor) {
|
||||
if (this.beanFactory != null) {
|
||||
this.beanFactory.setSerializationId(null);
|
||||
this.beanFactory = null;
|
||||
}
|
||||
DefaultListableBeanFactory beanFactory = this.beanFactory;
|
||||
if (beanFactory != null) {
|
||||
beanFactory.setSerializationId(null);
|
||||
this.beanFactory = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,20 +158,17 @@ public abstract class AbstractRefreshableApplicationContext extends AbstractAppl
|
||||
* i.e. has been refreshed at least once and not been closed yet.
|
||||
*/
|
||||
protected final boolean hasBeanFactory() {
|
||||
synchronized (this.beanFactoryMonitor) {
|
||||
return (this.beanFactory != null);
|
||||
}
|
||||
return (this.beanFactory != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ConfigurableListableBeanFactory getBeanFactory() {
|
||||
synchronized (this.beanFactoryMonitor) {
|
||||
if (this.beanFactory == null) {
|
||||
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
|
||||
"call 'refresh' before accessing beans via the ApplicationContext");
|
||||
}
|
||||
return this.beanFactory;
|
||||
DefaultListableBeanFactory beanFactory = this.beanFactory;
|
||||
if (beanFactory == null) {
|
||||
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
|
||||
"call 'refresh' before accessing beans via the ApplicationContext");
|
||||
}
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+7
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -160,8 +160,9 @@ public abstract class AbstractResourceBasedMessageSource extends AbstractMessage
|
||||
/**
|
||||
* Set the number of seconds to cache loaded properties files.
|
||||
* <ul>
|
||||
* <li>Default is "-1", indicating to cache forever (just like
|
||||
* {@code java.util.ResourceBundle}).
|
||||
* <li>Default is "-1", indicating to cache forever (matching the default behavior
|
||||
* of {@code java.util.ResourceBundle}). Note that this constant follows Spring
|
||||
* conventions, not {@link java.util.ResourceBundle.Control#getTimeToLive}.
|
||||
* <li>A positive number will cache loaded properties files for the given
|
||||
* number of seconds. This is essentially the interval between refresh checks.
|
||||
* Note that a refresh attempt will first check the last-modified timestamp
|
||||
@@ -184,8 +185,9 @@ public abstract class AbstractResourceBasedMessageSource extends AbstractMessage
|
||||
* Set the number of milliseconds to cache loaded properties files.
|
||||
* Note that it is common to set seconds instead: {@link #setCacheSeconds}.
|
||||
* <ul>
|
||||
* <li>Default is "-1", indicating to cache forever (just like
|
||||
* {@code java.util.ResourceBundle}).
|
||||
* <li>Default is "-1", indicating to cache forever (matching the default behavior
|
||||
* of {@code java.util.ResourceBundle}). Note that this constant follows Spring
|
||||
* conventions, not {@link java.util.ResourceBundle.Control#getTimeToLive}.
|
||||
* <li>A positive number will cache loaded properties files for the given
|
||||
* number of milliseconds. This is essentially the interval between refresh checks.
|
||||
* Note that a refresh attempt will first check the last-modified timestamp
|
||||
|
||||
+5
@@ -225,18 +225,22 @@ public class GenericGroovyApplicationContext extends GenericApplicationContext i
|
||||
|
||||
// Implementation of the GroovyObject interface
|
||||
|
||||
@Override
|
||||
public void setMetaClass(MetaClass metaClass) {
|
||||
this.metaClass = metaClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaClass getMetaClass() {
|
||||
return this.metaClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invokeMethod(String name, Object args) {
|
||||
return this.metaClass.invokeMethod(this, name, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(String property, Object newValue) {
|
||||
if (newValue instanceof BeanDefinition) {
|
||||
registerBeanDefinition(property, (BeanDefinition) newValue);
|
||||
@@ -246,6 +250,7 @@ public class GenericGroovyApplicationContext extends GenericApplicationContext i
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object getProperty(String property) {
|
||||
if (containsBean(property)) {
|
||||
|
||||
+19
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -237,6 +237,7 @@ public class ReloadableResourceBundleMessageSource extends AbstractResourceBased
|
||||
if (mergedHolder != null) {
|
||||
return mergedHolder;
|
||||
}
|
||||
|
||||
Properties mergedProps = newProperties();
|
||||
long latestTimestamp = -1;
|
||||
String[] basenames = StringUtils.toStringArray(getBasenameSet());
|
||||
@@ -253,6 +254,7 @@ public class ReloadableResourceBundleMessageSource extends AbstractResourceBased
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mergedHolder = new PropertiesHolder(mergedProps, latestTimestamp);
|
||||
PropertiesHolder existing = this.cachedMergedProperties.putIfAbsent(locale, mergedHolder);
|
||||
if (existing != null) {
|
||||
@@ -279,18 +281,28 @@ public class ReloadableResourceBundleMessageSource extends AbstractResourceBased
|
||||
return filenames;
|
||||
}
|
||||
}
|
||||
|
||||
// Filenames for given Locale
|
||||
List<String> filenames = new ArrayList<>(7);
|
||||
filenames.addAll(calculateFilenamesForLocale(basename, locale));
|
||||
if (isFallbackToSystemLocale() && !locale.equals(Locale.getDefault())) {
|
||||
List<String> fallbackFilenames = calculateFilenamesForLocale(basename, Locale.getDefault());
|
||||
for (String fallbackFilename : fallbackFilenames) {
|
||||
if (!filenames.contains(fallbackFilename)) {
|
||||
// Entry for fallback locale that isn't already in filenames list.
|
||||
filenames.add(fallbackFilename);
|
||||
|
||||
// Filenames for default Locale, if any
|
||||
if (isFallbackToSystemLocale()) {
|
||||
Locale defaultLocale = Locale.getDefault();
|
||||
if (!locale.equals(defaultLocale)) {
|
||||
List<String> fallbackFilenames = calculateFilenamesForLocale(basename, defaultLocale);
|
||||
for (String fallbackFilename : fallbackFilenames) {
|
||||
if (!filenames.contains(fallbackFilename)) {
|
||||
// Entry for fallback locale that isn't already in filenames list.
|
||||
filenames.add(fallbackFilename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Filename for default bundle file
|
||||
filenames.add(basename);
|
||||
|
||||
if (localeMap == null) {
|
||||
localeMap = new ConcurrentHashMap<>();
|
||||
Map<Locale, List<String>> existing = this.cachedFilenames.putIfAbsent(basename, localeMap);
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -43,6 +43,7 @@ public class StaticMessageSource extends AbstractMessageSource {
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected String resolveCodeWithoutArguments(String code, Locale locale) {
|
||||
return this.messages.get(code + '_' + locale.toString());
|
||||
}
|
||||
|
||||
+1
-2
@@ -61,14 +61,13 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
@Override
|
||||
public void registerFormatters(FormatterRegistry registry) {
|
||||
addDateConverters(registry);
|
||||
registry.addFormatterForFieldAnnotation(new DateTimeFormatAnnotationFormatterFactory());
|
||||
|
||||
// In order to retain back compatibility we only register Date/Calendar
|
||||
// types when a user defined formatter is specified (see SPR-10105)
|
||||
if (this.dateFormatter != null) {
|
||||
registry.addFormatter(this.dateFormatter);
|
||||
registry.addFormatterForFieldType(Calendar.class, this.dateFormatter);
|
||||
}
|
||||
registry.addFormatterForFieldAnnotation(new DateTimeFormatAnnotationFormatterFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+7
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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,6 +31,7 @@ import org.springframework.format.Formatter;
|
||||
* (which is commonly used for HTTP date header values), as of Spring 4.3.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Andrei Nevedomskii
|
||||
* @since 4.0
|
||||
* @see java.time.Instant#parse
|
||||
* @see java.time.format.DateTimeFormatter#ISO_INSTANT
|
||||
@@ -40,14 +41,14 @@ public class InstantFormatter implements Formatter<Instant> {
|
||||
|
||||
@Override
|
||||
public Instant parse(String text, Locale locale) throws ParseException {
|
||||
if (text.length() > 0 && Character.isDigit(text.charAt(0))) {
|
||||
// assuming UTC instant a la "2007-12-03T10:15:30.00Z"
|
||||
return Instant.parse(text);
|
||||
}
|
||||
else {
|
||||
if (text.length() > 0 && Character.isAlphabetic(text.charAt(0))) {
|
||||
// assuming RFC-1123 value a la "Tue, 3 Jun 2008 11:05:30 GMT"
|
||||
return Instant.from(DateTimeFormatter.RFC_1123_DATE_TIME.parse(text));
|
||||
}
|
||||
else {
|
||||
// assuming UTC instant a la "2007-12-03T10:15:30.00Z"
|
||||
return Instant.parse(text);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -207,7 +207,7 @@ public class InterfaceBasedMBeanInfoAssembler extends AbstractConfigurableMBeanI
|
||||
* configured interfaces and is public, otherwise {@code false}.
|
||||
*/
|
||||
private boolean isPublicInInterface(Method method, String beanKey) {
|
||||
return ((method.getModifiers() & Modifier.PUBLIC) > 0) && isDeclaredInInterface(method, beanKey);
|
||||
return Modifier.isPublic(method.getModifiers()) && isDeclaredInInterface(method, beanKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,6 +231,7 @@ public class InterfaceBasedMBeanInfoAssembler extends AbstractConfigurableMBeanI
|
||||
for (Class<?> ifc : ifaces) {
|
||||
for (Method ifcMethod : ifc.getMethods()) {
|
||||
if (ifcMethod.getName().equals(method.getName()) &&
|
||||
ifcMethod.getParameterCount() == method.getParameterCount() &&
|
||||
Arrays.equals(ifcMethod.getParameterTypes(), method.getParameterTypes())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -42,6 +42,6 @@ public enum RegistrationPolicy {
|
||||
* Registration should replace the affected MBean when attempting to register an MBean
|
||||
* under a name that already exists.
|
||||
*/
|
||||
REPLACE_EXISTING;
|
||||
REPLACE_EXISTING
|
||||
|
||||
}
|
||||
|
||||
+9
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -158,7 +158,14 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.groovyClassLoader = buildGroovyClassLoader(classLoader);
|
||||
if (classLoader instanceof GroovyClassLoader &&
|
||||
(this.compilerConfiguration == null ||
|
||||
((GroovyClassLoader) classLoader).hasCompatibleConfiguration(this.compilerConfiguration))) {
|
||||
this.groovyClassLoader = (GroovyClassLoader) classLoader;
|
||||
}
|
||||
else {
|
||||
this.groovyClassLoader = buildGroovyClassLoader(classLoader);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -50,7 +50,7 @@ import org.springframework.validation.annotation.Validated;
|
||||
* at the type level of the containing target class, applying to all public service methods
|
||||
* of that class. By default, JSR-303 will validate against its default group only.
|
||||
*
|
||||
* <p>As of Spring 5.0, this functionality requires a Bean Validation 1.1 provider.
|
||||
* <p>As of Spring 5.0, this functionality requires a Bean Validation 1.1+ provider.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
@@ -87,7 +87,6 @@ public class MethodValidationInterceptor implements MethodInterceptor {
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
// Avoid Validator invocation on FactoryBean.getObjectType/isSingleton
|
||||
if (isFactoryBeanMetadataMethod(invocation.getMethod())) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -50,7 +50,7 @@ import org.springframework.validation.annotation.Validated;
|
||||
* inline constraint annotations. Validation groups can be specified through {@code @Validated}
|
||||
* as well. By default, JSR-303 will validate against its default group only.
|
||||
*
|
||||
* <p>As of Spring 5.0, this functionality requires a Bean Validation 1.1 provider.
|
||||
* <p>As of Spring 5.0, this functionality requires a Bean Validation 1.1+ provider.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -60,7 +60,7 @@ public class CacheReproTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void spr11124MultipleAnnotations() throws Exception {
|
||||
public void spr11124MultipleAnnotations() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Spr11124Config.class);
|
||||
Spr11124Service bean = context.getBean(Spr11124Service.class);
|
||||
bean.single(2);
|
||||
@@ -71,7 +71,7 @@ public class CacheReproTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void spr11249PrimitiveVarargs() throws Exception {
|
||||
public void spr11249PrimitiveVarargs() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Spr11249Config.class);
|
||||
Spr11249Service bean = context.getBean(Spr11249Service.class);
|
||||
Object result = bean.doSomething("op", 2, 3);
|
||||
@@ -397,7 +397,6 @@ public class CacheReproTests {
|
||||
public TestBean insertItem(TestBean item) {
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Vendored
+5
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -35,8 +35,7 @@ import static org.junit.Assert.*;
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class ConcurrentMapCacheTests
|
||||
extends AbstractValueAdaptingCacheTests<ConcurrentMapCache> {
|
||||
public class ConcurrentMapCacheTests extends AbstractValueAdaptingCacheTests<ConcurrentMapCache> {
|
||||
|
||||
protected ConcurrentMap<Object, Object> nativeCache;
|
||||
|
||||
@@ -48,12 +47,11 @@ public class ConcurrentMapCacheTests
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
public void setup() {
|
||||
this.nativeCache = new ConcurrentHashMap<>();
|
||||
this.cache = new ConcurrentMapCache(CACHE_NAME, this.nativeCache, true);
|
||||
this.nativeCacheNoNull = new ConcurrentHashMap<>();
|
||||
this.cacheNoNull = new ConcurrentMapCache(CACHE_NAME_NO_NULL,
|
||||
this.nativeCacheNoNull, false);
|
||||
this.cacheNoNull = new ConcurrentMapCache(CACHE_NAME_NO_NULL, this.nativeCacheNoNull, false);
|
||||
this.cache.clear();
|
||||
}
|
||||
|
||||
@@ -72,6 +70,7 @@ public class ConcurrentMapCacheTests
|
||||
return this.nativeCache;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIsStoreByReferenceByDefault() {
|
||||
assertFalse(this.cache.isStoreByValue());
|
||||
|
||||
Vendored
+2
-2
@@ -44,7 +44,7 @@ public class SimpleKeyGeneratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleValue(){
|
||||
public void singleValue() {
|
||||
Object k1 = generateKey(new Object[] { "a" });
|
||||
Object k2 = generateKey(new Object[] { "a" });
|
||||
Object k3 = generateKey(new Object[] { "different" });
|
||||
@@ -56,7 +56,7 @@ public class SimpleKeyGeneratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleValues() {
|
||||
public void multipleValues() {
|
||||
Object k1 = generateKey(new Object[] { "a", 1, "b" });
|
||||
Object k2 = generateKey(new Object[] { "a", 1, "b" });
|
||||
Object k3 = generateKey(new Object[] { "b", 1, "a" });
|
||||
|
||||
+61
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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,16 +28,18 @@ import org.springframework.beans.BeanInstantiationException;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.annotation2.NamedStubDao2;
|
||||
import org.springframework.context.index.CandidateComponentsTestClassLoader;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@@ -102,10 +104,66 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
@Test
|
||||
public void testDoubleScan() {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
|
||||
int beanCount = scanner.scan(BASE_PACKAGE);
|
||||
assertEquals(12, beanCount);
|
||||
scanner.scan(BASE_PACKAGE);
|
||||
|
||||
ClassPathBeanDefinitionScanner scanner2 = new ClassPathBeanDefinitionScanner(context) {
|
||||
@Override
|
||||
protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
|
||||
super.postProcessBeanDefinition(beanDefinition, beanName);
|
||||
beanDefinition.setAttribute("someDifference", "someValue");
|
||||
}
|
||||
};
|
||||
scanner2.scan(BASE_PACKAGE);
|
||||
|
||||
assertTrue(context.containsBean("serviceInvocationCounter"));
|
||||
assertTrue(context.containsBean("fooServiceImpl"));
|
||||
assertTrue(context.containsBean("stubFooDao"));
|
||||
assertTrue(context.containsBean("myNamedComponent"));
|
||||
assertTrue(context.containsBean("myNamedDao"));
|
||||
assertTrue(context.containsBean("thoreau"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithIndex() {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.setClassLoader(CandidateComponentsTestClassLoader.index(
|
||||
ClassPathScanningCandidateComponentProviderTests.class.getClassLoader(),
|
||||
new ClassPathResource("spring.components", FooServiceImpl.class)));
|
||||
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
|
||||
int beanCount = scanner.scan(BASE_PACKAGE);
|
||||
assertEquals(12, beanCount);
|
||||
|
||||
assertTrue(context.containsBean("serviceInvocationCounter"));
|
||||
assertTrue(context.containsBean("fooServiceImpl"));
|
||||
assertTrue(context.containsBean("stubFooDao"));
|
||||
assertTrue(context.containsBean("myNamedComponent"));
|
||||
assertTrue(context.containsBean("myNamedDao"));
|
||||
assertTrue(context.containsBean("thoreau"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoubleScanWithIndex() {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.setClassLoader(CandidateComponentsTestClassLoader.index(
|
||||
ClassPathScanningCandidateComponentProviderTests.class.getClassLoader(),
|
||||
new ClassPathResource("spring.components", FooServiceImpl.class)));
|
||||
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
|
||||
int beanCount = scanner.scan(BASE_PACKAGE);
|
||||
assertEquals(12, beanCount);
|
||||
|
||||
ClassPathBeanDefinitionScanner scanner2 = new ClassPathBeanDefinitionScanner(context) {
|
||||
@Override
|
||||
protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
|
||||
super.postProcessBeanDefinition(beanDefinition, beanName);
|
||||
beanDefinition.setAttribute("someDifference", "someValue");
|
||||
}
|
||||
};
|
||||
scanner2.scan(BASE_PACKAGE);
|
||||
|
||||
assertTrue(context.containsBean("serviceInvocationCounter"));
|
||||
assertTrue(context.containsBean("fooServiceImpl"));
|
||||
|
||||
+41
-39
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -40,8 +40,8 @@ import example.scannable.sub.BarComponent;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.componentscan.gh24375.MyComponent;
|
||||
import org.springframework.context.index.CandidateComponentsTestClassLoader;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
@@ -80,18 +80,17 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
|
||||
provider.setResourceLoader(new DefaultResourceLoader(
|
||||
CandidateComponentsTestClassLoader.disableIndex(getClass().getClassLoader())));
|
||||
testDefault(provider, ScannedGenericBeanDefinition.class);
|
||||
testDefault(provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultsWithIndex() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
|
||||
provider.setResourceLoader(new DefaultResourceLoader(TEST_BASE_CLASSLOADER));
|
||||
testDefault(provider, AnnotatedGenericBeanDefinition.class);
|
||||
testDefault(provider);
|
||||
}
|
||||
|
||||
private void testDefault(ClassPathScanningCandidateComponentProvider provider,
|
||||
Class<? extends BeanDefinition> expectedBeanDefinitionType) {
|
||||
private void testDefault(ClassPathScanningCandidateComponentProvider provider) {
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
assertTrue(containsBeanClass(candidates, DefaultNamedComponent.class));
|
||||
assertTrue(containsBeanClass(candidates, NamedComponent.class));
|
||||
@@ -101,7 +100,7 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
assertTrue(containsBeanClass(candidates, ServiceInvocationCounter.class));
|
||||
assertTrue(containsBeanClass(candidates, BarComponent.class));
|
||||
assertEquals(7, candidates.size());
|
||||
assertBeanDefinitionType(candidates, expectedBeanDefinitionType);
|
||||
assertBeanDefinitionType(candidates);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -109,22 +108,21 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
|
||||
provider.setResourceLoader(new DefaultResourceLoader(
|
||||
CandidateComponentsTestClassLoader.disableIndex(getClass().getClassLoader())));
|
||||
testAntStyle(provider, ScannedGenericBeanDefinition.class);
|
||||
testAntStyle(provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void antStylePackageWithIndex() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
|
||||
provider.setResourceLoader(new DefaultResourceLoader(TEST_BASE_CLASSLOADER));
|
||||
testAntStyle(provider, AnnotatedGenericBeanDefinition.class);
|
||||
testAntStyle(provider);
|
||||
}
|
||||
|
||||
private void testAntStyle(ClassPathScanningCandidateComponentProvider provider,
|
||||
Class<? extends BeanDefinition> expectedBeanDefinitionType) {
|
||||
private void testAntStyle(ClassPathScanningCandidateComponentProvider provider) {
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE + ".**.sub");
|
||||
assertTrue(containsBeanClass(candidates, BarComponent.class));
|
||||
assertEquals(1, candidates.size());
|
||||
assertBeanDefinitionType(candidates, expectedBeanDefinitionType);
|
||||
assertBeanDefinitionType(candidates);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -151,7 +149,7 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
provider.addIncludeFilter(new AnnotationTypeFilter(Component.class));
|
||||
provider.resetFilters(true);
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
assertBeanDefinitionType(candidates, AnnotatedGenericBeanDefinition.class);
|
||||
assertBeanDefinitionType(candidates);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -159,20 +157,19 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
provider.setResourceLoader(new DefaultResourceLoader(
|
||||
CandidateComponentsTestClassLoader.disableIndex(getClass().getClassLoader())));
|
||||
testCustomAnnotationTypeIncludeFilter(provider, ScannedGenericBeanDefinition.class);
|
||||
testCustomAnnotationTypeIncludeFilter(provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customAnnotationTypeIncludeFilterWithIndex() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
provider.setResourceLoader(new DefaultResourceLoader(TEST_BASE_CLASSLOADER));
|
||||
testCustomAnnotationTypeIncludeFilter(provider, AnnotatedGenericBeanDefinition.class);
|
||||
testCustomAnnotationTypeIncludeFilter(provider);
|
||||
}
|
||||
|
||||
private void testCustomAnnotationTypeIncludeFilter(ClassPathScanningCandidateComponentProvider provider,
|
||||
Class<? extends BeanDefinition> expectedBeanDefinitionType) {
|
||||
private void testCustomAnnotationTypeIncludeFilter(ClassPathScanningCandidateComponentProvider provider) {
|
||||
provider.addIncludeFilter(new AnnotationTypeFilter(Component.class));
|
||||
testDefault(provider, expectedBeanDefinitionType);
|
||||
testDefault(provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -180,18 +177,17 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
provider.setResourceLoader(new DefaultResourceLoader(
|
||||
CandidateComponentsTestClassLoader.disableIndex(getClass().getClassLoader())));
|
||||
testCustomAssignableTypeIncludeFilter(provider, ScannedGenericBeanDefinition.class);
|
||||
testCustomAssignableTypeIncludeFilter(provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customAssignableTypeIncludeFilterWithIndex() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
provider.setResourceLoader(new DefaultResourceLoader(TEST_BASE_CLASSLOADER));
|
||||
testCustomAssignableTypeIncludeFilter(provider, AnnotatedGenericBeanDefinition.class);
|
||||
testCustomAssignableTypeIncludeFilter(provider);
|
||||
}
|
||||
|
||||
private void testCustomAssignableTypeIncludeFilter(ClassPathScanningCandidateComponentProvider provider,
|
||||
Class<? extends BeanDefinition> expectedBeanDefinitionType) {
|
||||
private void testCustomAssignableTypeIncludeFilter(ClassPathScanningCandidateComponentProvider provider) {
|
||||
provider.addIncludeFilter(new AssignableTypeFilter(FooService.class));
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
// Interfaces/Abstract class are filtered out automatically.
|
||||
@@ -199,7 +195,7 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
assertTrue(containsBeanClass(candidates, FooServiceImpl.class));
|
||||
assertTrue(containsBeanClass(candidates, ScopedProxyTestBean.class));
|
||||
assertEquals(3, candidates.size());
|
||||
assertBeanDefinitionType(candidates, expectedBeanDefinitionType);
|
||||
assertBeanDefinitionType(candidates);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -207,18 +203,17 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
provider.setResourceLoader(new DefaultResourceLoader(
|
||||
CandidateComponentsTestClassLoader.disableIndex(getClass().getClassLoader())));
|
||||
testCustomSupportedIncludeAndExcludeFilter(provider, ScannedGenericBeanDefinition.class);
|
||||
testCustomSupportedIncludeAndExcludeFilter(provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customSupportedIncludeAndExcludeFilterWithIndex() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
provider.setResourceLoader(new DefaultResourceLoader(TEST_BASE_CLASSLOADER));
|
||||
testCustomSupportedIncludeAndExcludeFilter(provider, AnnotatedGenericBeanDefinition.class);
|
||||
testCustomSupportedIncludeAndExcludeFilter(provider);
|
||||
}
|
||||
|
||||
private void testCustomSupportedIncludeAndExcludeFilter(ClassPathScanningCandidateComponentProvider provider,
|
||||
Class<? extends BeanDefinition> expectedBeanDefinitionType) {
|
||||
private void testCustomSupportedIncludeAndExcludeFilter(ClassPathScanningCandidateComponentProvider provider) {
|
||||
provider.addIncludeFilter(new AnnotationTypeFilter(Component.class));
|
||||
provider.addExcludeFilter(new AnnotationTypeFilter(Service.class));
|
||||
provider.addExcludeFilter(new AnnotationTypeFilter(Repository.class));
|
||||
@@ -227,7 +222,7 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
assertTrue(containsBeanClass(candidates, ServiceInvocationCounter.class));
|
||||
assertTrue(containsBeanClass(candidates, BarComponent.class));
|
||||
assertEquals(3, candidates.size());
|
||||
assertBeanDefinitionType(candidates, expectedBeanDefinitionType);
|
||||
assertBeanDefinitionType(candidates);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -240,7 +235,7 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
assertTrue(containsBeanClass(candidates, DefaultNamedComponent.class));
|
||||
assertEquals(1, candidates.size());
|
||||
assertBeanDefinitionType(candidates, ScannedGenericBeanDefinition.class);
|
||||
assertBeanDefinitionType(candidates);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -251,7 +246,7 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
assertTrue(containsBeanClass(candidates, StubFooDao.class));
|
||||
assertEquals(1, candidates.size());
|
||||
assertBeanDefinitionType(candidates, ScannedGenericBeanDefinition.class);
|
||||
assertBeanDefinitionType(candidates);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -260,7 +255,7 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
provider.setResourceLoader(new DefaultResourceLoader(
|
||||
CandidateComponentsTestClassLoader.disableIndex(getClass().getClassLoader())));
|
||||
provider.addExcludeFilter(new RegexPatternTypeFilter(Pattern.compile(TEST_BASE_PACKAGE + ".*Named.*")));
|
||||
testExclude(provider, ScannedGenericBeanDefinition.class);
|
||||
testExclude(provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -268,18 +263,17 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
|
||||
provider.setResourceLoader(new DefaultResourceLoader(TEST_BASE_CLASSLOADER));
|
||||
provider.addExcludeFilter(new RegexPatternTypeFilter(Pattern.compile(TEST_BASE_PACKAGE + ".*Named.*")));
|
||||
testExclude(provider, AnnotatedGenericBeanDefinition.class);
|
||||
testExclude(provider);
|
||||
}
|
||||
|
||||
private void testExclude(ClassPathScanningCandidateComponentProvider provider,
|
||||
Class<? extends BeanDefinition> expectedBeanDefinitionType) {
|
||||
private void testExclude(ClassPathScanningCandidateComponentProvider provider) {
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
assertTrue(containsBeanClass(candidates, FooServiceImpl.class));
|
||||
assertTrue(containsBeanClass(candidates, StubFooDao.class));
|
||||
assertTrue(containsBeanClass(candidates, ServiceInvocationCounter.class));
|
||||
assertTrue(containsBeanClass(candidates, BarComponent.class));
|
||||
assertEquals(4, candidates.size());
|
||||
assertBeanDefinitionType(candidates, expectedBeanDefinitionType);
|
||||
assertBeanDefinitionType(candidates);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -307,7 +301,7 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithAspectAnnotationOnly() throws Exception {
|
||||
public void testWithAspectAnnotationOnly() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
provider.addIncludeFilter(new AnnotationTypeFilter(Aspect.class));
|
||||
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
|
||||
@@ -501,6 +495,15 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void gh24375() {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
|
||||
Set<BeanDefinition> components = provider.findCandidateComponents(MyComponent.class.getPackage().getName());
|
||||
assertEquals(1, components.size());
|
||||
assertEquals(MyComponent.class.getName(), components.iterator().next().getBeanClassName());
|
||||
}
|
||||
|
||||
|
||||
private boolean containsBeanClass(Set<BeanDefinition> candidates, Class<?> beanClass) {
|
||||
for (BeanDefinition candidate : candidates) {
|
||||
if (beanClass.getName().equals(candidate.getBeanClassName())) {
|
||||
@@ -510,10 +513,9 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void assertBeanDefinitionType(Set<BeanDefinition> candidates,
|
||||
Class<? extends BeanDefinition> expectedType) {
|
||||
private void assertBeanDefinitionType(Set<BeanDefinition> candidates) {
|
||||
candidates.forEach(c -> {
|
||||
assertThat(c, is(instanceOf(expectedType)));
|
||||
assertThat(c, is(instanceOf(ScannedGenericBeanDefinition.class)));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -530,9 +530,10 @@ public class ImportSelectorTests {
|
||||
static Map<String, List<String>> allImports() {
|
||||
return TestImportGroup.imports.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap((entry) -> entry.getKey().getClassName(),
|
||||
.collect(Collectors.toMap(entry -> entry.getKey().getClassName(),
|
||||
Map.Entry::getValue));
|
||||
}
|
||||
|
||||
private final List<Entry> instanceImports = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.componentscan.gh24375;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface A {
|
||||
|
||||
@AliasFor("value")
|
||||
B other() default @B;
|
||||
|
||||
@AliasFor("other")
|
||||
B value() default @B;
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.componentscan.gh24375;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.ANNOTATION_TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface B {
|
||||
|
||||
String name() default "";
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.componentscan.gh24375;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@A(other = @B)
|
||||
public class MyComponent {
|
||||
}
|
||||
+6
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -794,6 +794,7 @@ public class AnnotationDrivenEventListenerTests {
|
||||
|
||||
@EventListener
|
||||
@Async
|
||||
@Override
|
||||
public void handleAsync(AnotherTestEvent event) {
|
||||
assertTrue(!Thread.currentThread().getName().equals(event.content));
|
||||
this.eventCollector.addEvent(this, event);
|
||||
@@ -820,6 +821,7 @@ public class AnnotationDrivenEventListenerTests {
|
||||
|
||||
@EventListener
|
||||
@Async
|
||||
@Override
|
||||
public void handleAsync(AnotherTestEvent event) {
|
||||
assertTrue(!Thread.currentThread().getName().equals(event.content));
|
||||
this.eventCollector.addEvent(this, event);
|
||||
@@ -902,7 +904,6 @@ public class AnnotationDrivenEventListenerTests {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@EventListener
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ConditionalEvent {
|
||||
@@ -934,18 +935,20 @@ public class AnnotationDrivenEventListenerTests {
|
||||
super.handle(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
@EventListener(condition = "#payload.startsWith('OK')")
|
||||
@Override
|
||||
public void handleString(String payload) {
|
||||
super.handleString(payload);
|
||||
}
|
||||
|
||||
@ConditionalEvent("#root.event.timestamp > #p0")
|
||||
@Override
|
||||
public void handleTimestamp(Long timestamp) {
|
||||
collectEvent(timestamp);
|
||||
}
|
||||
|
||||
@ConditionalEvent("@conditionEvaluator.valid(#p0)")
|
||||
@Override
|
||||
public void handleRatio(Double ratio) {
|
||||
collectEvent(ratio);
|
||||
}
|
||||
|
||||
+2
-2
@@ -92,7 +92,7 @@ public class CandidateComponentsIndexLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadIndexNoEntry() throws IOException {
|
||||
public void loadIndexNoEntry() {
|
||||
CandidateComponentsIndex index = CandidateComponentsIndexLoader.loadIndex(
|
||||
CandidateComponentsTestClassLoader.index(getClass().getClassLoader(),
|
||||
new ClassPathResource("empty-spring.components", getClass())));
|
||||
@@ -100,7 +100,7 @@ public class CandidateComponentsIndexLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadIndexWithException() throws IOException {
|
||||
public void loadIndexWithException() {
|
||||
final IOException cause = new IOException("test exception");
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage("Unable to load indexes");
|
||||
|
||||
+1
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -62,7 +62,6 @@ public class StaticMessageSourceTests extends AbstractApplicationContextTests {
|
||||
@Test
|
||||
@Override
|
||||
public void count() {
|
||||
// These are only checked for current Ctx (not parent ctx)
|
||||
assertCount(15);
|
||||
}
|
||||
|
||||
|
||||
+17
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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,7 @@ import static org.junit.Assert.*;
|
||||
*/
|
||||
public class DateFormattingTests {
|
||||
|
||||
private final FormattingConversionService conversionService = new FormattingConversionService();
|
||||
private FormattingConversionService conversionService;
|
||||
|
||||
private DataBinder binder;
|
||||
|
||||
@@ -58,6 +58,7 @@ public class DateFormattingTests {
|
||||
}
|
||||
|
||||
private void setup(DateFormatterRegistrar registrar) {
|
||||
conversionService = new FormattingConversionService();
|
||||
DefaultConversionService.addDefaultConverters(conversionService);
|
||||
registrar.registerFormatters(conversionService);
|
||||
|
||||
@@ -148,6 +149,20 @@ public class DateFormattingTests {
|
||||
assertEquals("10/31/09 1:05", binder.getBindingResult().getFieldValue("dateAnnotatedPattern"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBindDateAnnotatedPatternWithGlobalFormat() {
|
||||
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
|
||||
DateFormatter dateFormatter = new DateFormatter();
|
||||
dateFormatter.setIso(ISO.DATE_TIME);
|
||||
registrar.setFormatter(dateFormatter);
|
||||
setup(registrar);
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("dateAnnotatedPattern", "10/31/09 1:05");
|
||||
binder.bind(propertyValues);
|
||||
assertEquals(0, binder.getBindingResult().getErrorCount());
|
||||
assertEquals("10/31/09 1:05", binder.getBindingResult().getFieldValue("dateAnnotatedPattern"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBindDateTimeOverflow() {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.format.datetime.standard;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static java.time.Instant.MAX;
|
||||
import static java.time.Instant.MIN;
|
||||
import static java.time.ZoneId.systemDefault;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link InstantFormatter}.
|
||||
*
|
||||
* @author Andrei Nevedomskii
|
||||
* @author Sam Brannen
|
||||
* @since 5.1.12
|
||||
*/
|
||||
public class InstantFormatterTests {
|
||||
|
||||
private final InstantFormatter instantFormatter = new InstantFormatter();
|
||||
|
||||
|
||||
@Test
|
||||
public void should_parse_an_ISO_formatted_string_representation_of_an_Instant() {
|
||||
new ISOSerializedInstantProvider().provideArguments().forEach(input -> {
|
||||
try {
|
||||
Instant expected = DateTimeFormatter.ISO_INSTANT.parse(input, Instant::from);
|
||||
|
||||
Instant actual = instantFormatter.parse(input, null);
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_parse_an_RFC1123_formatted_string_representation_of_an_Instant() {
|
||||
new RFC1123SerializedInstantProvider().provideArguments().forEach(input -> {
|
||||
try {
|
||||
Instant expected = DateTimeFormatter.RFC_1123_DATE_TIME.parse(input, Instant::from);
|
||||
|
||||
Instant actual = instantFormatter.parse(input, null);
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_serialize_an_Instant_using_ISO_format_and_ignoring_Locale() {
|
||||
new RandomInstantProvider().randomInstantStream(MIN, MAX).forEach(instant -> {
|
||||
String expected = DateTimeFormatter.ISO_INSTANT.format(instant);
|
||||
|
||||
String actual = instantFormatter.print(instant, null);
|
||||
|
||||
assertEquals(expected, actual);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private static class RandomInstantProvider {
|
||||
|
||||
private static final long DATA_SET_SIZE = 10;
|
||||
|
||||
private static final Random random = new Random();
|
||||
|
||||
Stream<Instant> randomInstantStream(Instant min, Instant max) {
|
||||
return Stream.concat(Stream.of(Instant.now()), // make sure that the data set includes current instant
|
||||
random.longs(min.getEpochSecond(), max.getEpochSecond()).limit(DATA_SET_SIZE).mapToObj(Instant::ofEpochSecond));
|
||||
}
|
||||
}
|
||||
|
||||
private static class ISOSerializedInstantProvider extends RandomInstantProvider {
|
||||
|
||||
Stream<String> provideArguments() {
|
||||
return randomInstantStream(MIN, MAX).map(DateTimeFormatter.ISO_INSTANT::format);
|
||||
}
|
||||
}
|
||||
|
||||
private static class RFC1123SerializedInstantProvider extends RandomInstantProvider {
|
||||
|
||||
// RFC-1123 supports only 4-digit years
|
||||
private static final Instant min = Instant.parse("0000-01-01T00:00:00.00Z");
|
||||
|
||||
private static final Instant max = Instant.parse("9999-12-31T23:59:59.99Z");
|
||||
|
||||
|
||||
Stream<String> provideArguments() {
|
||||
return randomInstantStream(min, max)
|
||||
.map(DateTimeFormatter.RFC_1123_DATE_TIME.withZone(systemDefault())::format);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -79,11 +79,11 @@ dependencies {
|
||||
optional("io.reactivex.rxjava2:rxjava:${rxjava2Version}")
|
||||
optional("io.netty:netty-buffer")
|
||||
testCompile("io.projectreactor:reactor-test")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
|
||||
testCompile("javax.annotation:javax.annotation-api:1.3.2")
|
||||
testCompile("com.google.code.findbugs:jsr305:3.0.2")
|
||||
testCompile("org.xmlunit:xmlunit-matchers:2.6.2")
|
||||
testCompile("javax.xml.bind:jaxb-api:2.3.1")
|
||||
testCompile("com.fasterxml.woodstox:woodstox-core:5.2.0") {
|
||||
testCompile("com.fasterxml.woodstox:woodstox-core:5.3.0") {
|
||||
exclude group: "stax", module: "stax-api"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +336,15 @@ public class ReflectUtils {
|
||||
public static Constructor getConstructor(Class type, Class[] parameterTypes) {
|
||||
try {
|
||||
Constructor constructor = type.getDeclaredConstructor(parameterTypes);
|
||||
constructor.setAccessible(true);
|
||||
if (System.getSecurityManager() != null) {
|
||||
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
|
||||
constructor.setAccessible(true);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
else {
|
||||
constructor.setAccessible(true);
|
||||
}
|
||||
return constructor;
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
|
||||
@@ -259,6 +259,9 @@ public class Enhancer extends AbstractClassGenerator {
|
||||
public void setSuperclass(Class superclass) {
|
||||
if (superclass != null && superclass.isInterface()) {
|
||||
setInterfaces(new Class[]{superclass});
|
||||
// SPRING PATCH BEGIN
|
||||
setContextClass(superclass);
|
||||
// SPRING PATCH END
|
||||
}
|
||||
else if (superclass != null && superclass.equals(Object.class)) {
|
||||
// affects choice of ClassLoader
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -169,11 +169,12 @@ public final class GenericTypeResolver {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) genericType;
|
||||
Class<?>[] generics = new Class<?>[parameterizedType.getActualTypeArguments().length];
|
||||
Type[] typeArguments = parameterizedType.getActualTypeArguments();
|
||||
ResolvableType contextType = ResolvableType.forClass(contextClass);
|
||||
for (int i = 0; i < typeArguments.length; i++) {
|
||||
Type typeArgument = typeArguments[i];
|
||||
if (typeArgument instanceof TypeVariable) {
|
||||
ResolvableType resolvedTypeArgument = resolveVariable(
|
||||
(TypeVariable<?>) typeArgument, ResolvableType.forClass(contextClass));
|
||||
(TypeVariable<?>) typeArgument, contextType);
|
||||
if (resolvedTypeArgument != ResolvableType.NONE) {
|
||||
generics[i] = resolvedTypeArgument.resolve();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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,9 +18,6 @@ package org.springframework.core;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -34,8 +31,6 @@ import org.springframework.util.ClassUtils;
|
||||
@SuppressWarnings("unchecked")
|
||||
public abstract class KotlinDetector {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(KotlinDetector.class);
|
||||
|
||||
@Nullable
|
||||
private static final Class<? extends Annotation> kotlinMetadata;
|
||||
|
||||
@@ -53,9 +48,6 @@ public abstract class KotlinDetector {
|
||||
}
|
||||
kotlinMetadata = (Class<? extends Annotation>) metadata;
|
||||
kotlinReflectPresent = ClassUtils.isPresent("kotlin.reflect.full.KClasses", classLoader);
|
||||
if (kotlinMetadata != null && !kotlinReflectPresent) {
|
||||
logger.info("Kotlin reflection implementation not found at runtime, related features won't be available.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -872,6 +872,12 @@ public class ResolvableType implements Serializable {
|
||||
return forType(ownerType, this.variableResolver).resolveVariable(variable);
|
||||
}
|
||||
}
|
||||
if (this.type instanceof WildcardType) {
|
||||
ResolvableType resolved = resolveType().resolveVariable(variable);
|
||||
if (resolved != null) {
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
if (this.variableResolver != null) {
|
||||
return this.variableResolver.resolveVariable(variable);
|
||||
}
|
||||
@@ -982,7 +988,7 @@ public class ResolvableType implements Serializable {
|
||||
* using the full generic type information for assignability checks.
|
||||
* For example: {@code ResolvableType.forClass(MyArrayList.class)}.
|
||||
* @param clazz the class to introspect ({@code null} is semantically
|
||||
* equivalent to {@code Object.class} for typical use cases here}
|
||||
* equivalent to {@code Object.class} for typical use cases here)
|
||||
* @return a {@link ResolvableType} for the specified class
|
||||
* @see #forClass(Class, Class)
|
||||
* @see #forClassWithGenerics(Class, Class...)
|
||||
@@ -997,7 +1003,7 @@ public class ResolvableType implements Serializable {
|
||||
* {@link Class#isAssignableFrom}, which this serves as a wrapper for.
|
||||
* For example: {@code ResolvableType.forRawClass(List.class)}.
|
||||
* @param clazz the class to introspect ({@code null} is semantically
|
||||
* equivalent to {@code Object.class} for typical use cases here}
|
||||
* equivalent to {@code Object.class} for typical use cases here)
|
||||
* @return a {@link ResolvableType} for the specified class
|
||||
* @since 4.2
|
||||
* @see #forClass(Class)
|
||||
@@ -1485,10 +1491,10 @@ public class ResolvableType implements Serializable {
|
||||
@Override
|
||||
@Nullable
|
||||
public ResolvableType resolveVariable(TypeVariable<?> variable) {
|
||||
TypeVariable<?> variableToCompare = SerializableTypeWrapper.unwrap(variable);
|
||||
for (int i = 0; i < this.variables.length; i++) {
|
||||
TypeVariable<?> v1 = SerializableTypeWrapper.unwrap(this.variables[i]);
|
||||
TypeVariable<?> v2 = SerializableTypeWrapper.unwrap(variable);
|
||||
if (ObjectUtils.nullSafeEquals(v1, v2)) {
|
||||
TypeVariable<?> resolvedVariable = SerializableTypeWrapper.unwrap(this.variables[i]);
|
||||
if (ObjectUtils.nullSafeEquals(resolvedVariable, variableToCompare)) {
|
||||
return this.generics[i];
|
||||
}
|
||||
}
|
||||
|
||||
+29
-1
@@ -47,12 +47,40 @@ import org.springframework.util.MimeType;
|
||||
*/
|
||||
public abstract class AbstractDataBufferDecoder<T> extends AbstractDecoder<T> {
|
||||
|
||||
private int maxInMemorySize = -1;
|
||||
|
||||
|
||||
protected AbstractDataBufferDecoder(MimeType... supportedMimeTypes) {
|
||||
super(supportedMimeTypes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure a limit on the number of bytes that can be buffered whenever
|
||||
* the input stream needs to be aggregated. This can be a result of
|
||||
* decoding to a single {@code DataBuffer},
|
||||
* {@link java.nio.ByteBuffer ByteBuffer}, {@code byte[]},
|
||||
* {@link org.springframework.core.io.Resource Resource}, {@code String}, etc.
|
||||
* It can also occur when splitting the input stream, e.g. delimited text,
|
||||
* in which case the limit applies to data buffered between delimiters.
|
||||
* <p>By default in 5.1 this is set to -1, unlimited. In 5.2 the default
|
||||
* value for this limit is set to 256K.
|
||||
* @param byteCount the max number of bytes to buffer, or -1 for unlimited
|
||||
* @since 5.1.11
|
||||
*/
|
||||
public void setMaxInMemorySize(int byteCount) {
|
||||
this.maxInMemorySize = byteCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link #setMaxInMemorySize configured} byte count limit.
|
||||
* @since 5.1.11
|
||||
*/
|
||||
public int getMaxInMemorySize() {
|
||||
return this.maxInMemorySize;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Flux<T> decode(Publisher<DataBuffer> input, ResolvableType elementType,
|
||||
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
@@ -64,7 +92,7 @@ public abstract class AbstractDataBufferDecoder<T> extends AbstractDecoder<T> {
|
||||
public Mono<T> decodeToMono(Publisher<DataBuffer> input, ResolvableType elementType,
|
||||
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
|
||||
return DataBufferUtils.join(input)
|
||||
return DataBufferUtils.join(input, this.maxInMemorySize)
|
||||
.map(buffer -> decodeDataBuffer(buffer, elementType, mimeType, hints));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -25,14 +25,17 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferLimitException;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.core.io.buffer.LimitedDataBufferList;
|
||||
import org.springframework.core.io.buffer.PooledDataBuffer;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -92,11 +95,44 @@ public final class StringDecoder extends AbstractDataBufferDecoder<String> {
|
||||
|
||||
List<byte[]> delimiterBytes = getDelimiterBytes(mimeType);
|
||||
|
||||
Flux<DataBuffer> inputFlux = Flux.from(input)
|
||||
.flatMapIterable(buffer -> splitOnDelimiter(buffer, delimiterBytes))
|
||||
.bufferUntil(buffer -> buffer == END_FRAME)
|
||||
.map(StringDecoder::joinUntilEndFrame)
|
||||
.doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release);
|
||||
Flux<DataBuffer> inputFlux = Flux.defer(() -> {
|
||||
if (getMaxInMemorySize() != -1) {
|
||||
|
||||
// Passing limiter into endFrameAfterDelimiter helps to ensure that in case of one DataBuffer
|
||||
// containing multiple lines, the limit is checked and raised immediately without accumulating
|
||||
// subsequent lines. This is necessary because concatMapIterable doesn't respect doOnDiscard.
|
||||
// When reactor-core#1925 is resolved, we could replace bufferUntil with:
|
||||
|
||||
// .windowUntil(buffer -> buffer instanceof EndFrameBuffer)
|
||||
// .concatMap(fluxes -> fluxes.collect(() -> new LimitedDataBufferList(getMaxInMemorySize()), LimitedDataBufferList::add))
|
||||
|
||||
LimitedDataBufferList limiter = new LimitedDataBufferList(getMaxInMemorySize());
|
||||
|
||||
return Flux.from(input)
|
||||
.concatMapIterable(buffer -> splitOnDelimiter(buffer, delimiterBytes, limiter))
|
||||
.bufferUntil(buffer -> buffer == END_FRAME)
|
||||
.map(StringDecoder::joinUntilEndFrame)
|
||||
.doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release);
|
||||
}
|
||||
else {
|
||||
|
||||
// When the decoder is unlimited (-1), concatMapIterable will cache buffers that may not
|
||||
// be released if cancel is signalled before they are turned into String lines
|
||||
// (see test maxInMemoryLimitReleasesUnprocessedLinesWhenUnlimited).
|
||||
// When reactor-core#1925 is resolved, the workaround can be removed and the entire
|
||||
// else clause possibly dropped.
|
||||
|
||||
ConcatMapIterableDiscardWorkaroundCache cache = new ConcatMapIterableDiscardWorkaroundCache();
|
||||
|
||||
return Flux.from(input)
|
||||
.concatMapIterable(buffer -> cache.addAll(splitOnDelimiter(buffer, delimiterBytes, null)))
|
||||
.doOnNext(cache)
|
||||
.doOnCancel(cache)
|
||||
.bufferUntil(buffer -> buffer == END_FRAME)
|
||||
.map(StringDecoder::joinUntilEndFrame)
|
||||
.doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release);
|
||||
}
|
||||
});
|
||||
|
||||
return super.decode(inputFlux, elementType, mimeType, hints);
|
||||
}
|
||||
@@ -116,7 +152,9 @@ public final class StringDecoder extends AbstractDataBufferDecoder<String> {
|
||||
* Split the given data buffer on delimiter boundaries.
|
||||
* The returned Flux contains an {@link #END_FRAME} buffer after each delimiter.
|
||||
*/
|
||||
private List<DataBuffer> splitOnDelimiter(DataBuffer buffer, List<byte[]> delimiterBytes) {
|
||||
private List<DataBuffer> splitOnDelimiter(
|
||||
DataBuffer buffer, List<byte[]> delimiterBytes, @Nullable LimitedDataBufferList limiter) {
|
||||
|
||||
List<DataBuffer> frames = new ArrayList<>();
|
||||
try {
|
||||
do {
|
||||
@@ -138,15 +176,28 @@ public final class StringDecoder extends AbstractDataBufferDecoder<String> {
|
||||
buffer.readPosition(readPosition + length + matchingDelimiter.length);
|
||||
frames.add(DataBufferUtils.retain(frame));
|
||||
frames.add(END_FRAME);
|
||||
if (limiter != null) {
|
||||
limiter.add(frame); // enforce the limit
|
||||
limiter.clear();
|
||||
}
|
||||
}
|
||||
else {
|
||||
frame = buffer.slice(readPosition, buffer.readableByteCount());
|
||||
buffer.readPosition(readPosition + buffer.readableByteCount());
|
||||
frames.add(DataBufferUtils.retain(frame));
|
||||
if (limiter != null) {
|
||||
limiter.add(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (buffer.readableByteCount() > 0);
|
||||
}
|
||||
catch (DataBufferLimitException ex) {
|
||||
if (limiter != null) {
|
||||
limiter.releaseAndClear();
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
for (DataBuffer frame : frames) {
|
||||
DataBufferUtils.release(frame);
|
||||
@@ -283,4 +334,33 @@ public final class StringDecoder extends AbstractDataBufferDecoder<String> {
|
||||
new MimeType("text", "plain", DEFAULT_CHARSET), MimeTypeUtils.ALL);
|
||||
}
|
||||
|
||||
|
||||
private class ConcatMapIterableDiscardWorkaroundCache implements Consumer<DataBuffer>, Runnable {
|
||||
|
||||
private final List<DataBuffer> buffers = new ArrayList<>();
|
||||
|
||||
|
||||
public List<DataBuffer> addAll(List<DataBuffer> buffersToAdd) {
|
||||
this.buffers.addAll(buffersToAdd);
|
||||
return buffersToAdd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(DataBuffer dataBuffer) {
|
||||
this.buffers.remove(dataBuffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.buffers.forEach(buffer -> {
|
||||
try {
|
||||
DataBufferUtils.release(buffer);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// Keep going..
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user