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 0222cfa951..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. */ @@ -47,15 +41,15 @@ public final class ParseState { /** - * 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 ArrayDeque<>(); } /** - * Create a new {@code ParseState} whose {@link LinkedList} 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(); @@ -63,22 +57,22 @@ public final class ParseState { /** - * 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() { @@ -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 + "'"; 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 0f185dcf0b..427e2bec83 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 @@ -220,7 +220,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()) { @@ -285,7 +285,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()) { @@ -410,24 +410,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 @@ -443,7 +450,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; + } + } + } 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 eeeca3ceef..d52e336e11 100644 --- a/spring-core/src/main/java/org/springframework/util/FastByteArrayOutputStream.java +++ b/spring-core/src/main/java/org/springframework/util/FastByteArrayOutputStream.java @@ -32,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. @@ -290,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) {