Reject @Bean method with method-level @Autowired declaration

Closes gh-33051
This commit is contained in:
Juergen Hoeller
2024-06-17 21:08:21 +02:00
parent a58e27eded
commit 5c68f3f4ef
2 changed files with 20 additions and 4 deletions

View File

@@ -18,6 +18,7 @@ package org.springframework.context.annotation;
import java.util.Map; import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.parsing.Problem; import org.springframework.beans.factory.parsing.Problem;
import org.springframework.beans.factory.parsing.ProblemReporter; import org.springframework.beans.factory.parsing.ProblemReporter;
import org.springframework.core.type.MethodMetadata; import org.springframework.core.type.MethodMetadata;
@@ -45,6 +46,12 @@ final class BeanMethod extends ConfigurationMethod {
@Override @Override
@SuppressWarnings("NullAway") @SuppressWarnings("NullAway")
public void validate(ProblemReporter problemReporter) { public void validate(ProblemReporter problemReporter) {
if (getMetadata().getAnnotationAttributes(Autowired.class.getName()) != null) {
// declared as @Autowired: semantic mismatch since @Bean method arguments are autowired
// in any case whereas @Autowired methods are setter-like methods on the containing class
problemReporter.error(new AutowiredDeclaredMethodError());
}
if ("void".equals(getMetadata().getReturnTypeName())) { if ("void".equals(getMetadata().getReturnTypeName())) {
// declared as void: potential misuse of @Bean, maybe meant as init method instead? // declared as void: potential misuse of @Bean, maybe meant as init method instead?
problemReporter.error(new VoidDeclaredMethodError()); problemReporter.error(new VoidDeclaredMethodError());
@@ -89,6 +96,15 @@ final class BeanMethod extends ConfigurationMethod {
} }
private class AutowiredDeclaredMethodError extends Problem {
AutowiredDeclaredMethodError() {
super("@Bean method '%s' must not be declared as autowired; remove the method-level @Autowired annotation."
.formatted(getMetadata().getMethodName()), getResourceLocation());
}
}
private class VoidDeclaredMethodError extends Problem { private class VoidDeclaredMethodError extends Problem {
VoidDeclaredMethodError() { VoidDeclaredMethodError() {

View File

@@ -30,6 +30,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
@@ -47,6 +48,7 @@ import org.springframework.core.io.Resource;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/** /**
* System tests covering use of {@link Autowired} and {@link Value} within * System tests covering use of {@link Autowired} and {@link Value} within
@@ -187,10 +189,8 @@ class AutowiredConfigurationTests {
@Test @Test
void testValueInjectionWithAccidentalAutowiredAnnotations() { void testValueInjectionWithAccidentalAutowiredAnnotations() {
AnnotationConfigApplicationContext context = assertThatExceptionOfType(BeanDefinitionParsingException.class).isThrownBy(() ->
new AnnotationConfigApplicationContext(ValueConfigWithAccidentalAutowiredAnnotations.class); new AnnotationConfigApplicationContext(ValueConfigWithAccidentalAutowiredAnnotations.class));
doTestValueInjection(context);
context.close();
} }
private void doTestValueInjection(BeanFactory context) { private void doTestValueInjection(BeanFactory context) {