I’m relatively new to Spring and even newer to annotations and autowiring. I can’t figure out how to wire my beans. The idea is to switch between CacheService and NoCacheService by changing the application-config.xml but I cannot get past the exception.
Exception
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'Service' defined in ServletContext resource [/WEB-INF/application-config.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [webapp.Services]: Specified class is an interface
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:997)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:943)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:848)
<snip>
Classes:
package webapp;
interface Service {
List<String> get();
}
@Service("cache")
CacheService implements Service {
//from cache then from IO bound source
@Autowired
public CacheService(int v1, int v2)
...
}
@Service("nocache")
NoCacheService implements Service {
//from IO bound source
....
}
Controller:
@RequestMapping("/")
@Controller
public class ServiceController {
@Autowired
Service service;
...
}
application-config xml:
<mvc:annotation-driven />
<context:component-scan base-package="webapp"/>
<beans:bean id="Service" class="webapp.Service">
<beans:property name="cache" ref="cache" />
</beans:bean>
<beans:bean id="cache" class="webapp.CacheService">
<beans:constructor-arg index="0" value="50"/> <!-- v1 -->
<beans:constructor-arg index="1" value="100"/> <!-- v2 -->
</beans:bean>
<beans:bean id="nocache" class="webapp.NoCacheService">
</beans:bean>
You can choose to wire things using annotations or xml, in this specific case there are beans which are being configured both ways and that will cause the issues you are seeing. Let me try and enumerate some changes:
.1. Remove
<beans:bean id="Service" class="webapp.Service">as your<beans:property name="cache" ref="cache" />
</beans:bean>
webapp.Serviceis an interface and the reason for your error message..2. It will be better to instantiate CacheService through configuration, so just remove @Service annotation from it and retain only this:
.3. NoCacheService need not be in the xml file, it can be instantiated using component-scan the way you have already done.
.4. Now to injct the CacheService or NoCacheService, since there are two instances you have to indicate which one to inject into the Controller, which you can do this way: