From 60fa704f7836ee50a47fa82f25f8fd65deeaac1b Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 27 Aug 2020 14:13:33 +0200 Subject: [PATCH 1/4] Consistent behavior for overloaded @Bean methods with ASM processing Closes gh-25263 --- ...onfigurationClassBeanDefinitionReader.java | 20 +++++++--- .../ConfigurationClassProcessingTests.java | 39 ++++++++++++++++++- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java index 5f884f6fb5..bbf0c1f2cd 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java @@ -211,7 +211,7 @@ class ConfigurationClassBeanDefinitionReader { return; } - ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata); + ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata, beanName); beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource())); if (metadata.isStatic()) { @@ -276,7 +276,7 @@ class ConfigurationClassBeanDefinitionReader { new BeanDefinitionHolder(beanDef, beanName), this.registry, proxyMode == ScopedProxyMode.TARGET_CLASS); beanDefToRegister = new ConfigurationClassBeanDefinition( - (RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata); + (RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata, beanName); } if (logger.isTraceEnabled()) { @@ -398,24 +398,31 @@ class ConfigurationClassBeanDefinitionReader { private final MethodMetadata factoryMethodMetadata; - public ConfigurationClassBeanDefinition(ConfigurationClass configClass, MethodMetadata beanMethodMetadata) { + private final String derivedBeanName; + + public ConfigurationClassBeanDefinition( + ConfigurationClass configClass, MethodMetadata beanMethodMetadata, String derivedBeanName) { + this.annotationMetadata = configClass.getMetadata(); this.factoryMethodMetadata = beanMethodMetadata; + this.derivedBeanName = derivedBeanName; setResource(configClass.getResource()); setLenientConstructorResolution(false); } - public ConfigurationClassBeanDefinition( - RootBeanDefinition original, ConfigurationClass configClass, MethodMetadata beanMethodMetadata) { + public ConfigurationClassBeanDefinition(RootBeanDefinition original, + ConfigurationClass configClass, MethodMetadata beanMethodMetadata, String derivedBeanName) { super(original); this.annotationMetadata = configClass.getMetadata(); this.factoryMethodMetadata = beanMethodMetadata; + this.derivedBeanName = derivedBeanName; } private ConfigurationClassBeanDefinition(ConfigurationClassBeanDefinition original) { super(original); this.annotationMetadata = original.annotationMetadata; this.factoryMethodMetadata = original.factoryMethodMetadata; + this.derivedBeanName = original.derivedBeanName; } @Override @@ -431,7 +438,8 @@ class ConfigurationClassBeanDefinitionReader { @Override public boolean isFactoryMethod(Method candidate) { - return (super.isFactoryMethod(candidate) && BeanAnnotationHelper.isBeanAnnotated(candidate)); + return (super.isFactoryMethod(candidate) && BeanAnnotationHelper.isBeanAnnotated(candidate) && + BeanAnnotationHelper.determineBeanNameFor(candidate).equals(this.derivedBeanName)); } @Override diff --git a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java index 733e087954..92119a76b6 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java @@ -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. @@ -280,12 +280,32 @@ public class ConfigurationClassProcessingTests { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(ConfigWithApplicationListener.class); ctx.refresh(); + ConfigWithApplicationListener config = ctx.getBean(ConfigWithApplicationListener.class); assertThat(config.closed).isFalse(); ctx.close(); assertThat(config.closed).isTrue(); } + @Test + public void configurationWithOverloadedBeanMismatch() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.registerBeanDefinition("config", new RootBeanDefinition(OverloadedBeanMismatch.class)); + ctx.refresh(); + + TestBean tb = ctx.getBean(TestBean.class); + assertThat(tb.getLawyer()).isEqualTo(ctx.getBean(NestedTestBean.class)); + } + + @Test + public void configurationWithOverloadedBeanMismatchWithAsm() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.registerBeanDefinition("config", new RootBeanDefinition(OverloadedBeanMismatch.class.getName())); + ctx.refresh(); + + TestBean tb = ctx.getBean(TestBean.class); + assertThat(tb.getLawyer()).isEqualTo(ctx.getBean(NestedTestBean.class)); + } /** @@ -595,4 +615,21 @@ public class ConfigurationClassProcessingTests { } } + + @Configuration + public static class OverloadedBeanMismatch { + + @Bean(name = "other") + public NestedTestBean foo() { + return new NestedTestBean(); + } + + @Bean(name = "foo") + public TestBean foo(@Qualifier("other") NestedTestBean other) { + TestBean tb = new TestBean(); + tb.setLawyer(other); + return tb; + } + } + } From 589060d10fa20903ec75a75bd79111f46b10a5ab Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 27 Aug 2020 14:14:08 +0200 Subject: [PATCH 2/4] Avoid LinkedList performance issues through use of ArrayDeque Closes gh-25652 --- .../beans/factory/parsing/ParseState.java | 37 ++++++++++--------- .../util/FastByteArrayOutputStream.java | 11 +++--- .../org/springframework/util/StringUtils.java | 14 ++++--- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/parsing/ParseState.java b/spring-beans/src/main/java/org/springframework/beans/factory/parsing/ParseState.java index 36375ef84f..2ff49b1b8d 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/parsing/ParseState.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/parsing/ParseState.java @@ -16,12 +16,12 @@ package org.springframework.beans.factory.parsing; -import java.util.LinkedList; +import java.util.ArrayDeque; import org.springframework.lang.Nullable; /** - * Simple {@link LinkedList}-based structure for tracking the logical position during + * Simple {@link ArrayDeque}-based structure for tracking the logical position during * a parsing process. {@link Entry entries} are added to the LinkedList at * each point during the parse phase in a reader-specific manner. * @@ -30,6 +30,7 @@ import org.springframework.lang.Nullable; * error messages. * * @author Rob Harrop + * @author Juergen Hoeller * @since 2.0 */ public final class ParseState { @@ -40,45 +41,44 @@ public final class ParseState { private static final char TAB = '\t'; /** - * Internal {@link LinkedList} storage. + * Internal {@link ArrayDeque} storage. */ - private final LinkedList state; + private final ArrayDeque state; /** - * Create a new {@code ParseState} with an empty {@link LinkedList}. + * Create a new {@code ParseState} with an empty {@link ArrayDeque}. */ public ParseState() { - this.state = new LinkedList<>(); + this.state = new ArrayDeque<>(); } /** - * Create a new {@code ParseState} whose {@link LinkedList} is a {@link Object#clone clone} + * Create a new {@code ParseState} whose {@link ArrayDeque} is a {@link Object#clone clone} * of that of the passed in {@code ParseState}. */ - @SuppressWarnings("unchecked") private ParseState(ParseState other) { - this.state = (LinkedList) other.state.clone(); + this.state = other.state.clone(); } /** - * Add a new {@link Entry} to the {@link LinkedList}. + * Add a new {@link Entry} to the {@link ArrayDeque}. */ public void push(Entry entry) { this.state.push(entry); } /** - * Remove an {@link Entry} from the {@link LinkedList}. + * Remove an {@link Entry} from the {@link ArrayDeque}. */ public void pop() { this.state.pop(); } /** - * Return the {@link Entry} currently at the top of the {@link LinkedList} or - * {@code null} if the {@link LinkedList} is empty. + * Return the {@link Entry} currently at the top of the {@link ArrayDeque} or + * {@code null} if the {@link ArrayDeque} is empty. */ @Nullable public Entry peek() { @@ -100,15 +100,17 @@ public final class ParseState { @Override public String toString() { StringBuilder sb = new StringBuilder(); - for (int x = 0; x < this.state.size(); x++) { - if (x > 0) { + int i = 0; + for (ParseState.Entry entry : this.state) { + if (i > 0) { sb.append('\n'); - for (int y = 0; y < x; y++) { + for (int j = 0; j < i; j++) { sb.append(TAB); } sb.append("-> "); } - sb.append(this.state.get(x)); + sb.append(entry); + i++; } return sb.toString(); } @@ -118,7 +120,6 @@ public final class ParseState { * Marker interface for entries into the {@link ParseState}. */ public interface Entry { - } } diff --git a/spring-core/src/main/java/org/springframework/util/FastByteArrayOutputStream.java b/spring-core/src/main/java/org/springframework/util/FastByteArrayOutputStream.java index f8e484fae7..d52e336e11 100644 --- a/spring-core/src/main/java/org/springframework/util/FastByteArrayOutputStream.java +++ b/spring-core/src/main/java/org/springframework/util/FastByteArrayOutputStream.java @@ -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. @@ -20,8 +20,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.MessageDigest; +import java.util.ArrayDeque; +import java.util.Deque; import java.util.Iterator; -import java.util.LinkedList; import org.springframework.lang.Nullable; @@ -31,7 +32,7 @@ import org.springframework.lang.Nullable; * its sibling {@link ResizableByteArrayOutputStream}. * *

Unlike {@link java.io.ByteArrayOutputStream}, this implementation is backed - * by a {@link java.util.LinkedList} of {@code byte[]} instead of 1 constantly + * by an {@link java.util.ArrayDeque} of {@code byte[]} instead of 1 constantly * resizing {@code byte[]}. It does not copy buffers when it gets expanded. * *

The initial buffer is only created when the stream is first written. @@ -50,7 +51,7 @@ public class FastByteArrayOutputStream extends OutputStream { // The buffers used to store the content bytes - private final LinkedList buffers = new LinkedList<>(); + private final Deque buffers = new ArrayDeque<>(); // The size, in bytes, to use when allocating the first byte[] private final int initialBlockSize; @@ -289,7 +290,7 @@ public class FastByteArrayOutputStream extends OutputStream { } /** - * Create a new buffer and store it in the LinkedList + * Create a new buffer and store it in the ArrayDeque. *

Adds a new buffer that can store at least {@code minCapacity} bytes. */ private void addBuffer(int minCapacity) { diff --git a/spring-core/src/main/java/org/springframework/util/StringUtils.java b/spring-core/src/main/java/org/springframework/util/StringUtils.java index f627c8bf83..7867cda671 100644 --- a/spring-core/src/main/java/org/springframework/util/StringUtils.java +++ b/spring-core/src/main/java/org/springframework/util/StringUtils.java @@ -18,14 +18,15 @@ package org.springframework.util; import java.io.ByteArrayOutputStream; import java.nio.charset.Charset; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Deque; import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedHashSet; -import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Properties; @@ -655,6 +656,9 @@ public abstract class StringUtils { * inner simple dots. *

The result is convenient for path comparison. For other uses, * notice that Windows separators ("\") are replaced by simple slashes. + *

NOTE that {@code cleanPath} should not be depended + * upon in a security context. Other mechanisms should be used to prevent + * path-traversal issues. * @param path the original path * @return the normalized path */ @@ -690,7 +694,7 @@ public abstract class StringUtils { } String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR); - LinkedList pathElements = new LinkedList<>(); + Deque pathElements = new ArrayDeque<>(); int tops = 0; for (int i = pathArray.length - 1; i >= 0; i--) { @@ -709,7 +713,7 @@ public abstract class StringUtils { } else { // Normal path element found. - pathElements.add(0, element); + pathElements.addFirst(element); } } } @@ -720,11 +724,11 @@ public abstract class StringUtils { } // Remaining top paths need to be retained. for (int i = 0; i < tops; i++) { - pathElements.add(0, TOP_PATH); + pathElements.addFirst(TOP_PATH); } // If nothing else left, at least explicitly point to current path. if (pathElements.size() == 1 && pathElements.getLast().isEmpty() && !prefix.endsWith(FOLDER_SEPARATOR)) { - pathElements.add(0, CURRENT_PATH); + pathElements.addFirst(CURRENT_PATH); } return prefix + collectionToDelimitedString(pathElements, FOLDER_SEPARATOR); From cf2e0c7959fad8d8f79ffba9a3e14edd65831940 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 27 Aug 2020 14:14:44 +0200 Subject: [PATCH 3/4] Selected use of ArrayList instead of LinkedList in common places See gh-25652 --- .../beans/factory/support/ReplaceOverride.java | 7 ++++--- .../validation/AbstractBindingResult.java | 10 +++++----- .../springframework/validation/AbstractErrors.java | 8 ++++---- .../HandlerMethodArgumentResolverComposite.java | 6 +++--- .../HandlerMethodArgumentResolverComposite.java | 11 +++++------ .../messaging/simp/stomp/StompEncoder.java | 7 +++---- .../persistenceunit/MutablePersistenceUnitInfo.java | 12 ++++++------ .../PersistenceAnnotationBeanPostProcessor.java | 5 ++--- .../config/TxAdviceBeanDefinitionParser.java | 10 +++++----- .../HandlerMethodArgumentResolverComposite.java | 6 +++--- .../web/util/pattern/RegexPathElement.java | 6 +++--- .../HandlerMethodArgumentResolverComposite.java | 11 +++++------ 12 files changed, 48 insertions(+), 51 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ReplaceOverride.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ReplaceOverride.java index c94ce67176..ea8c3495c5 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ReplaceOverride.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ReplaceOverride.java @@ -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. @@ -17,7 +17,7 @@ package org.springframework.beans.factory.support; import java.lang.reflect.Method; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; import org.springframework.lang.Nullable; @@ -39,7 +39,7 @@ public class ReplaceOverride extends MethodOverride { private final String methodReplacerBeanName; - private List typeIdentifiers = new LinkedList<>(); + private final List typeIdentifiers = new ArrayList<>(); /** @@ -70,6 +70,7 @@ public class ReplaceOverride extends MethodOverride { this.typeIdentifiers.add(identifier); } + @Override public boolean matches(Method method) { if (!method.getName().equals(getMethodName())) { diff --git a/spring-context/src/main/java/org/springframework/validation/AbstractBindingResult.java b/spring-context/src/main/java/org/springframework/validation/AbstractBindingResult.java index eb8b310468..b8857b15b5 100644 --- a/spring-context/src/main/java/org/springframework/validation/AbstractBindingResult.java +++ b/spring-context/src/main/java/org/springframework/validation/AbstractBindingResult.java @@ -18,11 +18,11 @@ package org.springframework.validation; import java.beans.PropertyEditor; import java.io.Serializable; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -50,7 +50,7 @@ public abstract class AbstractBindingResult extends AbstractErrors implements Bi private MessageCodesResolver messageCodesResolver = new DefaultMessageCodesResolver(); - private final List errors = new LinkedList<>(); + private final List errors = new ArrayList<>(); private final Map> fieldTypes = new HashMap<>(); @@ -145,7 +145,7 @@ public abstract class AbstractBindingResult extends AbstractErrors implements Bi @Override public List getGlobalErrors() { - List result = new LinkedList<>(); + List result = new ArrayList<>(); for (ObjectError objectError : this.errors) { if (!(objectError instanceof FieldError)) { result.add(objectError); @@ -167,7 +167,7 @@ public abstract class AbstractBindingResult extends AbstractErrors implements Bi @Override public List getFieldErrors() { - List result = new LinkedList<>(); + List result = new ArrayList<>(); for (ObjectError objectError : this.errors) { if (objectError instanceof FieldError) { result.add((FieldError) objectError); @@ -189,7 +189,7 @@ public abstract class AbstractBindingResult extends AbstractErrors implements Bi @Override public List getFieldErrors(String field) { - List result = new LinkedList<>(); + List result = new ArrayList<>(); String fixedField = fixedField(field); for (ObjectError objectError : this.errors) { if (objectError instanceof FieldError && isMatchingFieldError(fixedField, (FieldError) objectError)) { diff --git a/spring-context/src/main/java/org/springframework/validation/AbstractErrors.java b/spring-context/src/main/java/org/springframework/validation/AbstractErrors.java index 355f087262..9556dc3a28 100644 --- a/spring-context/src/main/java/org/springframework/validation/AbstractErrors.java +++ b/spring-context/src/main/java/org/springframework/validation/AbstractErrors.java @@ -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,9 @@ package org.springframework.validation; import java.io.Serializable; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Collections; import java.util.Deque; -import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; @@ -146,7 +146,7 @@ public abstract class AbstractErrors implements Errors, Serializable { @Override public List getAllErrors() { - List result = new LinkedList<>(); + List result = new ArrayList<>(); result.addAll(getGlobalErrors()); result.addAll(getFieldErrors()); return Collections.unmodifiableList(result); @@ -199,7 +199,7 @@ public abstract class AbstractErrors implements Errors, Serializable { @Override public List getFieldErrors(String field) { List fieldErrors = getFieldErrors(); - List result = new LinkedList<>(); + List result = new ArrayList<>(); String fixedField = fixedField(field); for (FieldError error : fieldErrors) { if (isMatchingFieldError(fixedField, error)) { diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/HandlerMethodArgumentResolverComposite.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/HandlerMethodArgumentResolverComposite.java index 937befe33e..7bde7fb3d3 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/HandlerMethodArgumentResolverComposite.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/HandlerMethodArgumentResolverComposite.java @@ -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,8 @@ package org.springframework.messaging.handler.invocation; +import java.util.ArrayList; import java.util.Collections; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -37,7 +37,7 @@ import org.springframework.messaging.Message; */ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver { - private final List argumentResolvers = new LinkedList<>(); + private final List argumentResolvers = new ArrayList<>(); private final Map argumentResolverCache = new ConcurrentHashMap<>(256); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/HandlerMethodArgumentResolverComposite.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/HandlerMethodArgumentResolverComposite.java index 6822b29f63..3009a05e56 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/HandlerMethodArgumentResolverComposite.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/HandlerMethodArgumentResolverComposite.java @@ -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,8 @@ package org.springframework.messaging.handler.invocation.reactive; +import java.util.ArrayList; import java.util.Collections; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -42,7 +42,7 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu protected final Log logger = LogFactory.getLog(getClass()); - private final List argumentResolvers = new LinkedList<>(); + private final List argumentResolvers = new ArrayList<>(); private final Map argumentResolverCache = new ConcurrentHashMap<>(256); @@ -113,9 +113,8 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu public Mono resolveArgument(MethodParameter parameter, Message message) { HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); if (resolver == null) { - throw new IllegalArgumentException( - "Unsupported parameter type [" + parameter.getParameterType().getName() + "]." + - " supportsParameter should be called first."); + throw new IllegalArgumentException("Unsupported parameter type [" + + parameter.getParameterType().getName() + "]. supportsParameter should be called first."); } return resolver.resolveArgument(parameter, message); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompEncoder.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompEncoder.java index a9c163ac69..175043f586 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompEncoder.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompEncoder.java @@ -17,9 +17,9 @@ package org.springframework.messaging.simp.stomp; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -228,15 +228,14 @@ public class StompEncoder { void add(byte b); byte[] toByteArray(); - } + @SuppressWarnings("serial") - private static class DefaultResult extends LinkedList implements Result { + private static class DefaultResult extends ArrayList implements Result { private int size; - public void add(byte[] bytes) { this.size += bytes.length; super.add(bytes); diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java index c4c2b1938e..b006f76bfa 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java @@ -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. @@ -17,7 +17,7 @@ package org.springframework.orm.jpa.persistenceunit; import java.net.URL; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; import java.util.Properties; @@ -61,16 +61,16 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo { @Nullable private DataSource jtaDataSource; - private final List mappingFileNames = new LinkedList<>(); + private final List mappingFileNames = new ArrayList<>(); - private List jarFileUrls = new LinkedList<>(); + private final List jarFileUrls = new ArrayList<>(); @Nullable private URL persistenceUnitRootUrl; - private final List managedClassNames = new LinkedList<>(); + private final List managedClassNames = new ArrayList<>(); - private final List managedPackages = new LinkedList<>(); + private final List managedPackages = new ArrayList<>(); private boolean excludeUnlistedClasses = false; diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java b/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java index 3560c02cde..044ffd71a1 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java @@ -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. @@ -24,7 +24,6 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; @@ -423,7 +422,7 @@ public class PersistenceAnnotationBeanPostProcessor Class targetClass = clazz; do { - final LinkedList currElements = new LinkedList<>(); + final List currElements = new ArrayList<>(); ReflectionUtils.doWithLocalFields(targetClass, field -> { if (field.isAnnotationPresent(PersistenceContext.class) || diff --git a/spring-tx/src/main/java/org/springframework/transaction/config/TxAdviceBeanDefinitionParser.java b/spring-tx/src/main/java/org/springframework/transaction/config/TxAdviceBeanDefinitionParser.java index 41a1e61370..e763ade8fb 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/config/TxAdviceBeanDefinitionParser.java +++ b/spring-tx/src/main/java/org/springframework/transaction/config/TxAdviceBeanDefinitionParser.java @@ -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. @@ -16,7 +16,7 @@ package org.springframework.transaction.config; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; import org.w3c.dom.Element; @@ -127,14 +127,14 @@ class TxAdviceBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { attribute.setReadOnly(Boolean.parseBoolean(methodEle.getAttribute(READ_ONLY_ATTRIBUTE))); } - List rollbackRules = new LinkedList<>(); + List rollbackRules = new ArrayList<>(1); if (methodEle.hasAttribute(ROLLBACK_FOR_ATTRIBUTE)) { String rollbackForValue = methodEle.getAttribute(ROLLBACK_FOR_ATTRIBUTE); - addRollbackRuleAttributesTo(rollbackRules,rollbackForValue); + addRollbackRuleAttributesTo(rollbackRules, rollbackForValue); } if (methodEle.hasAttribute(NO_ROLLBACK_FOR_ATTRIBUTE)) { String noRollbackForValue = methodEle.getAttribute(NO_ROLLBACK_FOR_ATTRIBUTE); - addNoRollbackRuleAttributesTo(rollbackRules,noRollbackForValue); + addNoRollbackRuleAttributesTo(rollbackRules, noRollbackForValue); } attribute.setRollbackRules(rollbackRules); diff --git a/spring-web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java b/spring-web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java index 2b1cba3b05..60a27b9ae5 100644 --- a/spring-web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java +++ b/spring-web/src/main/java/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java @@ -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,8 @@ package org.springframework.web.method.support; +import java.util.ArrayList; import java.util.Collections; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -38,7 +38,7 @@ import org.springframework.web.context.request.NativeWebRequest; */ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver { - private final List argumentResolvers = new LinkedList<>(); + private final List argumentResolvers = new ArrayList<>(); private final Map argumentResolverCache = new ConcurrentHashMap<>(256); diff --git a/spring-web/src/main/java/org/springframework/web/util/pattern/RegexPathElement.java b/spring-web/src/main/java/org/springframework/web/util/pattern/RegexPathElement.java index dd55d5c39c..f326a87e13 100644 --- a/spring-web/src/main/java/org/springframework/web/util/pattern/RegexPathElement.java +++ b/spring-web/src/main/java/org/springframework/web/util/pattern/RegexPathElement.java @@ -16,7 +16,7 @@ package org.springframework.web.util.pattern; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -40,7 +40,7 @@ class RegexPathElement extends PathElement { private static final String DEFAULT_VARIABLE_PATTERN = "(.*)"; - private char[] regex; + private final char[] regex; private final boolean caseSensitive; @@ -48,7 +48,7 @@ class RegexPathElement extends PathElement { private int wildcardCount; - private final List variableNames = new LinkedList<>(); + private final List variableNames = new ArrayList<>(); RegexPathElement(int pos, char[] regex, boolean caseSensitive, char[] completePattern, char separator) { diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolverComposite.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolverComposite.java index 5af5d2679d..1161c1c8e4 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolverComposite.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/HandlerMethodArgumentResolverComposite.java @@ -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,8 +16,8 @@ package org.springframework.web.reactive.result.method; +import java.util.ArrayList; import java.util.Collections; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -43,7 +43,7 @@ class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentRes protected final Log logger = LogFactory.getLog(getClass()); - private final List argumentResolvers = new LinkedList<>(); + private final List argumentResolvers = new ArrayList<>(); private final Map argumentResolverCache = new ConcurrentHashMap<>(256); @@ -116,9 +116,8 @@ class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentRes HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); if (resolver == null) { - throw new IllegalArgumentException( - "Unsupported parameter type [" + parameter.getParameterType().getName() + "]." + - " supportsParameter should be called first."); + throw new IllegalArgumentException("Unsupported parameter type [" + + parameter.getParameterType().getName() + "]. supportsParameter should be called first."); } return resolver.resolveArgument(parameter, bindingContext, exchange); } From a8b295c5164dfb50a1c47e1084c3f79dd30a5a3a Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 27 Aug 2020 14:37:42 +0200 Subject: [PATCH 4/4] Consistent javadoc for ParseState and its entry classes --- .../aop/config/AdviceEntry.java | 7 ++++--- .../aop/config/AdvisorEntry.java | 5 +++-- .../aop/config/AspectEntry.java | 5 +++-- .../aop/config/PointcutEntry.java | 6 ++++-- .../beans/factory/parsing/BeanEntry.java | 7 +++---- .../beans/factory/parsing/ParseState.java | 20 +++++++------------ .../beans/factory/parsing/PropertyEntry.java | 8 +++----- .../beans/factory/parsing/QualifierEntry.java | 11 +++++++--- 8 files changed, 35 insertions(+), 34 deletions(-) diff --git a/spring-aop/src/main/java/org/springframework/aop/config/AdviceEntry.java b/spring-aop/src/main/java/org/springframework/aop/config/AdviceEntry.java index f9869a5f9b..7d9b2ad2dc 100644 --- a/spring-aop/src/main/java/org/springframework/aop/config/AdviceEntry.java +++ b/spring-aop/src/main/java/org/springframework/aop/config/AdviceEntry.java @@ -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. @@ -30,13 +30,14 @@ public class AdviceEntry implements ParseState.Entry { /** - * Creates a new instance of the {@link AdviceEntry} class. - * @param kind the kind of advice represented by this entry (before, after, around, etc.) + * Create a new {@code AdviceEntry} instance. + * @param kind the kind of advice represented by this entry (before, after, around) */ public AdviceEntry(String kind) { this.kind = kind; } + @Override public String toString() { return "Advice (" + this.kind + ")"; diff --git a/spring-aop/src/main/java/org/springframework/aop/config/AdvisorEntry.java b/spring-aop/src/main/java/org/springframework/aop/config/AdvisorEntry.java index 1f7ba05962..1a8b45c482 100644 --- a/spring-aop/src/main/java/org/springframework/aop/config/AdvisorEntry.java +++ b/spring-aop/src/main/java/org/springframework/aop/config/AdvisorEntry.java @@ -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. @@ -30,13 +30,14 @@ public class AdvisorEntry implements ParseState.Entry { /** - * Creates a new instance of the {@link AdvisorEntry} class. + * Create a new {@code AdvisorEntry} instance. * @param name the bean name of the advisor */ public AdvisorEntry(String name) { this.name = name; } + @Override public String toString() { return "Advisor '" + this.name + "'"; diff --git a/spring-aop/src/main/java/org/springframework/aop/config/AspectEntry.java b/spring-aop/src/main/java/org/springframework/aop/config/AspectEntry.java index 13633bc2a2..2d4360048c 100644 --- a/spring-aop/src/main/java/org/springframework/aop/config/AspectEntry.java +++ b/spring-aop/src/main/java/org/springframework/aop/config/AspectEntry.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 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,7 +34,7 @@ public class AspectEntry implements ParseState.Entry { /** - * Create a new AspectEntry. + * Create a new {@code AspectEntry} instance. * @param id the id of the aspect element * @param ref the bean name referenced by this aspect element */ @@ -43,6 +43,7 @@ public class AspectEntry implements ParseState.Entry { this.ref = ref; } + @Override public String toString() { return "Aspect: " + (StringUtils.hasLength(this.id) ? "id='" + this.id + "'" : "ref='" + this.ref + "'"); diff --git a/spring-aop/src/main/java/org/springframework/aop/config/PointcutEntry.java b/spring-aop/src/main/java/org/springframework/aop/config/PointcutEntry.java index 950f8da387..e6066c513e 100644 --- a/spring-aop/src/main/java/org/springframework/aop/config/PointcutEntry.java +++ b/spring-aop/src/main/java/org/springframework/aop/config/PointcutEntry.java @@ -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. @@ -28,14 +28,16 @@ public class PointcutEntry implements ParseState.Entry { private final String name; + /** - * Creates a new instance of the {@link PointcutEntry} class. + * Create a new {@code PointcutEntry} instance. * @param name the bean name of the pointcut */ public PointcutEntry(String name) { this.name = name; } + @Override public String toString() { return "Pointcut '" + this.name + "'"; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/parsing/BeanEntry.java b/spring-beans/src/main/java/org/springframework/beans/factory/parsing/BeanEntry.java index 207650a27b..b1fded25d1 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/parsing/BeanEntry.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/parsing/BeanEntry.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2006 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. @@ -24,18 +24,17 @@ package org.springframework.beans.factory.parsing; */ public class BeanEntry implements ParseState.Entry { - private String beanDefinitionName; + private final String beanDefinitionName; /** - * Creates a new instance of {@link BeanEntry} class. + * Create a new {@code BeanEntry} instance. * @param beanDefinitionName the name of the associated bean definition */ public BeanEntry(String beanDefinitionName) { this.beanDefinitionName = beanDefinitionName; } - @Override public String toString() { return "Bean '" + this.beanDefinitionName + "'"; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/parsing/ParseState.java b/spring-beans/src/main/java/org/springframework/beans/factory/parsing/ParseState.java index 2ff49b1b8d..0277bc0a0f 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/parsing/ParseState.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/parsing/ParseState.java @@ -22,12 +22,11 @@ import org.springframework.lang.Nullable; /** * Simple {@link ArrayDeque}-based structure for tracking the logical position during - * a parsing process. {@link Entry entries} are added to the LinkedList at - * each point during the parse phase in a reader-specific manner. + * a parsing process. {@link Entry entries} are added to the ArrayDeque at each point + * during the parse phase in a reader-specific manner. * *

Calling {@link #toString()} will render a tree-style view of the current logical - * position in the parse phase. This representation is intended for use in - * error messages. + * position in the parse phase. This representation is intended for use in error messages. * * @author Rob Harrop * @author Juergen Hoeller @@ -35,11 +34,6 @@ import org.springframework.lang.Nullable; */ public final class ParseState { - /** - * Tab character used when rendering the tree-style representation. - */ - private static final char TAB = '\t'; - /** * Internal {@link ArrayDeque} storage. */ @@ -54,8 +48,8 @@ public final class ParseState { } /** - * Create a new {@code ParseState} whose {@link ArrayDeque} is a {@link Object#clone clone} - * of that of the passed in {@code ParseState}. + * Create a new {@code ParseState} whose {@link ArrayDeque} is a clone + * of the state in the passed-in {@code ParseState}. */ private ParseState(ParseState other) { this.state = other.state.clone(); @@ -99,13 +93,13 @@ public final class ParseState { */ @Override public String toString() { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(64); int i = 0; for (ParseState.Entry entry : this.state) { if (i > 0) { sb.append('\n'); for (int j = 0; j < i; j++) { - sb.append(TAB); + sb.append('\t'); } sb.append("-> "); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/parsing/PropertyEntry.java b/spring-beans/src/main/java/org/springframework/beans/factory/parsing/PropertyEntry.java index 983e72101b..c20235a09b 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/parsing/PropertyEntry.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/parsing/PropertyEntry.java @@ -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. @@ -30,14 +30,12 @@ public class PropertyEntry implements ParseState.Entry { /** - * Creates a new instance of the {@link PropertyEntry} class. + * Create a new {@code PropertyEntry} instance. * @param name the name of the JavaBean property represented by this instance - * @throws IllegalArgumentException if the supplied {@code name} is {@code null} - * or consists wholly of whitespace */ public PropertyEntry(String name) { if (!StringUtils.hasText(name)) { - throw new IllegalArgumentException("Invalid property name '" + name + "'."); + throw new IllegalArgumentException("Invalid property name '" + name + "'"); } this.name = name; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/parsing/QualifierEntry.java b/spring-beans/src/main/java/org/springframework/beans/factory/parsing/QualifierEntry.java index 8fc3207e80..45283e5838 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/parsing/QualifierEntry.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/parsing/QualifierEntry.java @@ -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. @@ -26,16 +26,21 @@ import org.springframework.util.StringUtils; */ public class QualifierEntry implements ParseState.Entry { - private String typeName; + private final String typeName; + /** + * Create a new {@code QualifierEntry} instance. + * @param typeName the name of the qualifier type + */ public QualifierEntry(String typeName) { if (!StringUtils.hasText(typeName)) { - throw new IllegalArgumentException("Invalid qualifier type '" + typeName + "'."); + throw new IllegalArgumentException("Invalid qualifier type '" + typeName + "'"); } this.typeName = typeName; } + @Override public String toString() { return "Qualifier '" + this.typeName + "'";