Fundo:
Eu tenho um aplicativo Spring 2.5 / Java / Tomcat. Existe o seguinte bean, que é usado em todo o aplicativo em muitos lugares
public class HibernateDeviceDao implements DeviceDao
e o seguinte bean que é novo:
public class JdbcDeviceDao implements DeviceDao
O primeiro bean está configurado para isso (todos os beans do pacote estão incluídos)
<context:component-scan base-package="com.initech.service.dao.hibernate" />
O segundo (novo) bean é configurado separadamente
<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
<property name="dataSource" ref="jdbcDataSource">
</bean>
Isso resulta (é claro) em uma exceção ao iniciar o servidor:
a exceção aninhada é org.springframework.beans.factory.NoSuchBeanDefinitionException: nenhum bean exclusivo do tipo [com.sevenp.mobile.samplemgmt.service.dao.DeviceDao] é definido: bean correspondente único esperado, mas localizado 2: [deviceDao, jdbcDeviceDao]
de uma classe tentando autowire o bean como este
@Autowired
private DeviceDao hibernateDevicDao;
porque existem dois beans implementando a mesma interface.
A questão:
É possível configurar os beans para que
1. Não preciso fazer alterações nas classes existentes, que já possuem o HibernateDeviceDao
cabeamento automático
2. ainda sendo capaz de usar o segundo (novo) bean como este:
@Autowired
@Qualifier("jdbcDeviceDao")
Ou seja, eu precisaria de uma maneira de configurar o HibernateDeviceDao
bean como o padrão a ser conectado automaticamente, permitindo simultaneamente o uso de um JdbcDeviceDao
quando especificando explicitamente isso com a @Qualifier
anotação.
O que eu já tentei:
Eu tentei definir a propriedade
autowire-candidate="false"
na configuração do bean para JdbcDeviceDao:
<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao" autowire-candidate="false">
<property name="dataSource" ref="jdbcDataSource"/>
</bean>
porque a documentação do Spring diz que
Indica se esse bean deve ou não ser considerado ao procurar candidatos correspondentes para satisfazer os requisitos de conexão automática de outro bean. Observe que isso não afeta as referências explícitas por nome, que serão resolvidas mesmo que o bean especificado não esteja marcado como candidato a fio automático. *
o que eu interpretei como significando que eu ainda podia fazer a ligação automática JdbcDeviceDao
usando a @Qualifier
anotação e ter o HibernateDeviceDao
bean como padrão. Aparentemente, minha interpretação não estava correta, pois isso resulta na seguinte mensagem de erro ao iniciar o servidor:
Dependência não satisfeita do tipo [classe com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao]: esperado pelo menos 1 bean correspondente
vindo da classe em que tentei fazer a fiação automática do bean com um qualificador:
@Autowired
@Qualifier("jdbcDeviceDao")
Solução:
A sugestão de skaffman de tentar a anotação @Resource funcionou. Portanto, a configuração tem candidato a fio automático definido como false para jdbcDeviceDao e, ao usar o jdbcDeviceDao, refiro-me a ela usando a anotação @Resource (em vez de @Qualifier):
@Resource(name = "jdbcDeviceDao")
private JdbcDeviceListItemDao jdbcDeviceDao;