Skip to content

Introduce autowiring support for individual handler method parameters [SPR-14056] #18628

Closed as not planned
@spring-projects-issues

Description

@spring-projects-issues

Sam Brannen opened SPR-14056 and commented

Status Quo

Spring supports autowiring of dependencies into fields, constructors, and methods; however, there is currently no first-class support for autowiring an individual parameter in a method or constructor.

Spring 5.0's JUnit 5 support demonstrates that it is already possible to implement such a feature with zero changes to core Spring; however, it would be very helpful if the necessary code were hidden behind first-class methods in Spring (see the isAutowirable and resolveDependency methods in ParameterAutowireUtils).

Impetus for Change

For traditional dependency injection use cases, there is no need to inject an individual parameter; however, JUnit 5 introduces a ParameterResolver extension API (analogous to Spring MVC's HandlerMethodArgumentResolver) that allows multiple, competing extension providers to inject values into constructors or test methods. In such a scenario, Spring is not the sole entity performing injection, and Spring therefore cannot simply perform injection for the entire constructor or method (as would be the case for an @Autowired method). Rather, the Spring TestContext Framework (TCF) needs a mechanism for resolving dependencies for individual method parameters (preferably via the java.lang.reflect.Parameter API).

Although the primary impetus is proper JUnit 5 support in the TCF, such a feature could be applied to MVC handler methods, JMS listener methods, etc.

Working Solution

The following excerpt from org.springframework.test.context.junit.jupiter.ParameterAutowireUtils demonstrates how such a feature can be implemented.

static boolean isAutowirable(Parameter parameter) {
	return ApplicationContext.class.isAssignableFrom(parameter.getType())
			|| AnnotatedElementUtils.hasAnnotation(parameter, Autowired.class)
			|| AnnotatedElementUtils.hasAnnotation(parameter, Qualifier.class)
			|| AnnotatedElementUtils.hasAnnotation(parameter, Value.class);
}

static Object resolveDependency(Parameter parameter, Class<?> containingClass, ApplicationContext applicationContext) {
	boolean required = findMergedAnnotation(parameter, Autowired.class).map(Autowired::required).orElse(true);
	MethodParameter methodParameter = SynthesizingMethodParameter.forParameter(parameter);
	DependencyDescriptor descriptor = new DependencyDescriptor(methodParameter, required);
	descriptor.setContainingClass(containingClass);
	return applicationContext.getAutowireCapableBeanFactory().resolveDependency(descriptor, null);
}

private static <A extends Annotation> Optional<A> findMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
	return Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(element, annotationType));
}

Deliverables

  • Decide if Spring should support autowiring of individual method parameters as a first-class citizen alongside the existing support for fields, methods, and constructors.

Issue Links:

Referenced from: commits d7fe92d, 35eb52e

3 votes, 7 watchers

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: coreIssues in core modules (aop, beans, core, context, expression)status: supersededAn issue that has been superseded by anothertype: enhancementA general enhancement

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions