Implement equals, hashCode, & toString in BeanMethod and *Metadata types

Prior to this commit, ConfigurationClass implemented equals(),
hashCode(), and toString(), but BeanMethod did not.

This commit introduces equals(), hashCode(), and toString()
implementations in BeanMethod for consistency with ConfigurationClass
to make it possible to use BeanMethod instances to index additional
metadata as well.

In order to properly implement equals() in BeanMethod, the method
argument types are required, but these are not directly available in
BeanMethod. However, they are available via ASM when processing @Bean
methods. This commit therefore implements equals(), hashCode(), and
toString() in SimpleMethodMetadata which BeanMethod delegates to.

For completeness, this commit also implements equals(), hashCode(), and
toString() in StandardClassMetadata, StandardMethodMetadata, and
SimpleAnnotationMetadata.

Closes gh-27076
This commit is contained in:
Sam Brannen
2021-06-23 14:27:51 +02:00
parent 882004fc9b
commit 2bc7a3aa0a
11 changed files with 452 additions and 12 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@ import org.springframework.util.StringUtils;
* to introspect a given {@code Class}.
*
* @author Juergen Hoeller
* @author Sam Brannen
* @since 2.5
*/
public class StandardClassMetadata implements ClassMetadata {
@@ -119,4 +120,20 @@ public class StandardClassMetadata implements ClassMetadata {
return StringUtils.toStringArray(memberClassNames);
}
@Override
public boolean equals(@Nullable Object obj) {
return ((this == obj) || ((obj instanceof StandardClassMetadata) &&
getIntrospectedClass().equals(((StandardClassMetadata) obj).getIntrospectedClass())));
}
@Override
public int hashCode() {
return getIntrospectedClass().hashCode();
}
@Override
public String toString() {
return getClassName();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ import org.springframework.util.MultiValueMap;
* @author Mark Pollack
* @author Chris Beams
* @author Phillip Webb
* @author Sam Brannen
* @since 3.0
*/
public class StandardMethodMetadata implements MethodMetadata {
@@ -150,4 +151,20 @@ public class StandardMethodMetadata implements MethodMetadata {
annotationName, classValuesAsString, false);
}
@Override
public boolean equals(@Nullable Object obj) {
return ((this == obj) || ((obj instanceof StandardMethodMetadata) &&
this.introspectedMethod.equals(((StandardMethodMetadata) obj).introspectedMethod)));
}
@Override
public int hashCode() {
return this.introspectedMethod.hashCode();
}
@Override
public String toString() {
return this.introspectedMethod.toString();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ import org.springframework.lang.Nullable;
* {@link SimpleAnnotationMetadataReadingVisitor}.
*
* @author Phillip Webb
* @author Sam Brannen
* @since 5.2
*/
final class SimpleAnnotationMetadata implements AnnotationMetadata {
@@ -156,4 +157,20 @@ final class SimpleAnnotationMetadata implements AnnotationMetadata {
return this.annotations;
}
@Override
public boolean equals(@Nullable Object obj) {
return ((this == obj) || ((obj instanceof SimpleAnnotationMetadata) &&
this.className.equals(((SimpleAnnotationMetadata) obj).className)));
}
@Override
public int hashCode() {
return this.className.hashCode();
}
@Override
public String toString() {
return this.className;
}
}

View File

@@ -19,11 +19,13 @@ package org.springframework.core.type.classreading;
import org.springframework.asm.Opcodes;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.type.MethodMetadata;
import org.springframework.lang.Nullable;
/**
* {@link MethodMetadata} created from a {@link SimpleMethodMetadataReadingVisitor}.
*
* @author Phillip Webb
* @author Sam Brannen
* @since 5.2
*/
final class SimpleMethodMetadata implements MethodMetadata {
@@ -36,16 +38,20 @@ final class SimpleMethodMetadata implements MethodMetadata {
private final String returnTypeName;
// The source implements equals(), hashCode(), and toString() for the underlying method.
private final Object source;
private final MergedAnnotations annotations;
public SimpleMethodMetadata(String methodName, int access, String declaringClassName,
String returnTypeName, MergedAnnotations annotations) {
SimpleMethodMetadata(String methodName, int access, String declaringClassName,
String returnTypeName, Object source, MergedAnnotations annotations) {
this.methodName = methodName;
this.access = access;
this.declaringClassName = declaringClassName;
this.returnTypeName = returnTypeName;
this.source = source;
this.annotations = annotations;
}
@@ -94,4 +100,20 @@ final class SimpleMethodMetadata implements MethodMetadata {
return this.annotations;
}
@Override
public boolean equals(@Nullable Object obj) {
return ((this == obj) || ((obj instanceof SimpleMethodMetadata) &&
this.source.equals(((SimpleMethodMetadata) obj).source)));
}
@Override
public int hashCode() {
return this.source.hashCode();
}
@Override
public String toString() {
return this.source.toString();
}
}

View File

@@ -81,8 +81,8 @@ final class SimpleMethodMetadataReadingVisitor extends MethodVisitor {
if (!this.annotations.isEmpty()) {
String returnTypeName = Type.getReturnType(this.descriptor).getClassName();
MergedAnnotations annotations = MergedAnnotations.of(this.annotations);
SimpleMethodMetadata metadata = new SimpleMethodMetadata(this.methodName,
this.access, this.declaringClassName, returnTypeName, annotations);
SimpleMethodMetadata metadata = new SimpleMethodMetadata(this.methodName, this.access,
this.declaringClassName, returnTypeName, getSource(), annotations);
this.consumer.accept(metadata);
}
}