[java] 동일한 인터페이스를 구현하는 두 개의 bean을 자동 배선-기본 bean을 autowire로 설정하는 방법은 무엇입니까?
배경:
Spring 2.5 / Java / Tomcat 애플리케이션이 있습니다. 응용 프로그램 전체에서 여러 곳에서 사용되는 다음 Bean이 있습니다.
public class HibernateDeviceDao implements DeviceDao
그리고 다음과 같은 새로운 bean :
public class JdbcDeviceDao implements DeviceDao
첫 번째 Bean이 구성되었습니다 (패키지의 모든 Bean이 포함됨)
<context:component-scan base-package="com.initech.service.dao.hibernate" />
두 번째 (새) Bean은 별도로 구성됩니다.
<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
<property name="dataSource" ref="jdbcDataSource">
</bean>
서버를 시작할 때 (물론) 예외가 발생합니다.
중첩 된 예외는 org.springframework.beans.factory.NoSuchBeanDefinitionException : [com.sevenp.mobile.samplemgmt.service.dao.DeviceDao] 유형의 고유 한 Bean이 정의되지 않았습니다. 단일 일치 Bean이 예상되지만 발견됨 2 : [deviceDao, jdbcDeviceDao]
이처럼 콩을 자동으로 연결하려고하는 클래스에서
@Autowired
private DeviceDao hibernateDevicDao;
동일한 인터페이스를 구현하는 두 개의 Bean이 있기 때문입니다.
질문:
Bean을 구성 할 수 있습니까?
1. 나는 이미 가지고있는 기존의 클래스를 변경할 필요가 없습니다 HibernateDeviceDao
를 autowire
2. 여전히 다음과 같이 두 번째 (새) Bean을 사용할 수 있습니다.
@Autowired
@Qualifier("jdbcDeviceDao")
즉, HibernateDeviceDao
bean을 기본 유선으로 자동 연결되도록 bean 을 구성하는 방법이 필요합니다 . 주석 JdbcDeviceDao
과 함께 명시 적으로 지정할 때 동시에 사용할 수 @Qualifier
있습니다.
내가 이미 시도한 것 :
속성 설정을 시도했습니다
autowire-candidate="false"
JdbcDeviceDao의 Bean 구성에서 :
<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao" autowire-candidate="false">
<property name="dataSource" ref="jdbcDataSource"/>
</bean>
스프링 문서에 따르면
다른 Bean의 자동 배선 요구 사항을 충족시키기 위해 일치하는 후보를 찾을 때이 Bean을 고려해야하는지 여부를 나타냅니다. 지정된 Bean이 자동 와이어 후보로 표시되지 않은 경우에도 이름으로 명시적인 참조에 영향을 미치지 않습니다. *
주석을 JdbcDeviceDao
사용하여 autowire 를 계속 사용할 수 있으며 기본 Bean을 @Qualifier
가질 수 있음을 의미했습니다 HibernateDeviceDao
. 서버를 시작할 때 다음과 같은 오류 메시지가 표시되므로 내 해석이 올바르지 않은 것 같습니다.
[class com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao] 유형의 충족되지 않은 종속성 : 하나 이상의 일치하는 Bean이 예상됩니다.
한정자를 사용하여 Bean을 자동 배선하려고 시도한 클래스에서 왔습니다.
@Autowired
@Qualifier("jdbcDeviceDao")
해결책:
@Resource 주석을 사용해 보겠다는 skaffman의 제안 이 효과가있었습니다. 따라서 구성에는 jdbcDeviceDao에 대해 자동 와이어 후보가 false로 설정되어 있으며 jdbcDeviceDao를 사용할 때 @Qualifier 대신 @Resource 주석을 사용하여 참조합니다.
@Resource(name = "jdbcDeviceDao")
private JdbcDeviceListItemDao jdbcDeviceDao;
답변
나는와 최대 절전 모드 DAO 클래스를 표시하는 게 좋을 것 @Primary
, 즉 (당신이 사용하는 가정 @Repository
에서 HibernateDeviceDao
)
@Primary
@Repository
public class HibernateDeviceDao implements DeviceDao
이 방법으로 autowire-candidate
다른 Bean을 사용할 필요없이 기본 자동 와이어 후보로 선택됩니다 .
또한을 사용하는 대신 특정 콩을 따기 @Autowired @Qualifier
위해 사용 @Resource
하는 것이 더 우아하다는 것을 알았습니다.
@Resource(name="jdbcDeviceDao")
DeviceDao deviceDao;
답변
무엇에 대해 @Primary
?
여러 후보가 단일 값 종속성 을 자동 와이어 링 할 수있는 경우 Bean에 우선 순위를 지정해야 함을 나타냅니다 . 후보자 사이에 정확히 하나의 ‘기본’Bean이 존재하면 자동 연결된 값이됩니다. 이 주석은 의미 적 으로 Spring XML 의
<bean>
요소primary
속성 과 동일합니다 .
@Primary
public class HibernateDeviceDao implements DeviceDao
또는 Jdbc 버전을 기본적으로 사용하려는 경우 :
<bean id="jdbcDeviceDao" primary="true" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
@Primary
또한 주석을 작성하여 프로덕션 Bean을 스텁 된 버전으로 쉽게 바꿀 수있는 경우 통합 테스트에 유용합니다.
답변
Spring 2.5의 경우는 없습니다 @Primary
. 유일한 방법은을 사용하는 것 @Qualifier
입니다.
답변
The use of @Qualifier will solve the issue.
Explained as below example :
public interface PersonType {} // MasterInterface
@Component(value="1.2")
public class Person implements PersonType { //Bean implementing the interface
@Qualifier("1.2")
public void setPerson(PersonType person) {
this.person = person;
}
}
@Component(value="1.5")
public class NewPerson implements PersonType {
@Qualifier("1.5")
public void setNewPerson(PersonType newPerson) {
this.newPerson = newPerson;
}
}
Now get the application context object in any component class :
Object obj= BeanFactoryAnnotationUtils.qualifiedBeanOfType((ctx).getAutowireCapableBeanFactory(), PersonType.class, type);//type is the qualifier id
you can the object of class of which qualifier id is passed.
답변
@Resource (name = “{your child class name}”)이 작동하지만 @Autowired가 작동하지 않는 이유는 일치 순서의 차이 때문입니다.
@Autowire
유형, 한정자, 이름 의 일치 순서
@Resource
Name, Type, Qualifier 의 일치 순서
자세한 설명은 여기에서 찾을 수 있습니다.
주입 및 리소스 및 자동 유선 주석
이 경우 부모 클래스 또는 인터페이스에서 상속 된 다른 자식 클래스는 동일한 유형이기 때문에 @Autowire를 혼동합니다. @Resource는 Name을 첫 번째로 일치하는 우선 순위로 사용하므로 작동합니다.