Reputation: 51
I'm using constructor-based dependency injection to inject a javax.inject.Provider<T>
to a service. With Spring Framework (4.2.5), NoSuchBeanDefinitionException
will be thrown saying "No qualifying bean of type [T] found for dependency. Why is T
expected by Spring while injecting javax.inject.Provider<T>
?
Here's the sample code:
Provider:
import javax.inject.Provider;
public class MessageProvider implements Provider<String> {
@Override
public String get() {
return "Hello!";
}
}
Service:
import javax.inject.Inject;
import javax.inject.Provider;
public class GreetingService {
private final String message;
@Inject
GreetingService(Provider<String> provider) {
// GreetingService(MessageProvider provider) { // this works!
this.message = provider.get();
}
public String greeting() {
return message;
}
}
Test:
import org.junit.Test;
import static org.junit.Assert.*;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class GreetingServiceTest {
@Test
public void testSomeMethod() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(MessageProvider.class);
ctx.register(GreetingService.class);
ctx.refresh();
GreetingService bean = ctx.getBean(GreetingService.class);
String message = bean.greeting();
assertNotNull(message);
}
}
And here's the error message:
Error creating bean with name 'greetingService': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [GreetingService]: Constructor threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
Upvotes: 1
Views: 1451
Reputation: 2737
You're question is a bit ambiguous. Are you asking why Spring needs a bean that can create a T
or are you asking why Spring isn't injecting an instance of your MessageProvider
class?
If your question is the former then the problem you are facing is that Provider<T>
is an interface, not a class. When you inject Provider<String>
Spring says, "Hmm, I don't see any bean definition for the Provider
interface, is there another way I can satisfy this dependency?" And Spring's answer is, "Yes, I can create an instance of org.springframework.beans.support.DefaultListableBeanFactory$DependencyProvider
, but only if I know how to create T
, i.e. there is a bean definition for T
."
Your sample code should work if you added a configuration class to define a bean of type String
:
@Configuration
public class MyConfiguration
{
@Bean
public String getMessage()
{
return "Hello!";
}
}
But if you are asking why Spring isn't injecting an instance of your MessageProvider
class I suspect the problem is that it's not properly defined. You could add a qualifier to the MessageProvider
definition and usage
@Component("MyMessageProvider")
public class MessageProvider implements Provider<String> {
...
and
@Inject
GreetingService(@Qualifier("MyMessageProvider") Provider<String> provider) {
...
to say exactly which Provider
implementation you want injected.
Upvotes: 0