This is an issue that gets me once every blue moon. Lets say that I have two classes DependencyClass
and MainClass
:
@Transactional
@Service
class DependencyClass implements IDependencyClass {
}
class MainClass {
@Autowired
private IDependencyClass insert;
}
DependencyClass
makes use of Spring's @Transactional
support, which is provided through AOP Proxies. This code works when I fire it up. However, if I add another implementation, and want to change the code to the following:
@Transactional
@Service
class DependencyClass implements IDependencyClass {
}
@Transactional
@Service
class DependencyClassAlternate implements IDependencyClass {
}
class MainClass {
@Autowired
private DependencyClass dc;
@Autowired
private DependencyClassAlternate dca;
}
I get this nasty on the application startup:
NoSuchBeanDefinitionException: No matching bean of type [DependencyClass] found for dependency
The reason for this is simple. Within the Spring container, the concrete class DependencyClass
has been replaced by a proxy. Therefore, as far as the system is concerned, there is no matching bean of type DependencyClass
.
Inevitably, when this occurs, I spend too much time looking to other issues with my application context setup. However, the solution is easy and straightforward, once you realize what the problem is:
@Transactional
@Service("dc")
class DependencyClass implements IDependencyClass {
}
@Transactional
@Service("dca")
class DependencyClassAlternate implements IDependencyClass {
}
class MainClass {
@Autowired
@Qualifier("dc")
private IDependencyClass dc;
@Autowired
@Qualifier("dca")
private IDependencyClass dca;
}
Basically, one needs to change the type back to an interface, then use named services and the @Qualifer
annotation to inject the desired dependency.