- 동작흐름.
1. beanfactory 에서 후보 bean을 가져온다. (by type) - @Qualifier 지정자가 있을 경우, 후보 bean을 지정자와 매치하는 것만 찾음
2-0. 후보가 없으면, 에러 끝.
2-1. 1개 일 경우, 반환 끝.
2-2. 2개 이상 일 경우. (fallback 상태)
이런 경우, fallback 상태로 처리 (is smart?)
2-2-1
각 후보 bean 에서 primary 표시자 유무를 찾는다. (@Primary annotation)
있는 경우, primary 로 지정된 bean 을 반환. (2개 이상 primary 로 지정 하면?)
2-2-2
primary 조차 없는 경우.
filedname(변수명)과 동일한 bean id가 있다면 반환.
2-2-3
그것 조차 없으면, 에러.
code
AutowiredAnnotationBeanPostProcessor.inject
-> beanFactory.resolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter);
-> DefaultListableBeanFactory.doResolveDependency
-> DefaultListableBeanFactory.findAutowireCandidates
-> DefaultListableBeanFactory.determinePrimaryCandidate
/**
* Determine the primary autowire candidate in the given set of beans.
* @param candidateBeans a Map of candidate names and candidate instances
* that match the required type, as returned by {@link #findAutowireCandidates}
* @param descriptor the target dependency to match against
* @return the name of the primary candidate, or <code>null</code> if none found
*/
protected String determinePrimaryCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) {
String primaryBeanName = null;
String fallbackBeanName = null;
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
if (isPrimary(candidateBeanName, beanInstance)) {
if (primaryBeanName != null) {
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
if (candidateLocal == primaryLocal) {
throw new NoSuchBeanDefinitionException(descriptor.getDependencyType(),
"more than one 'primary' bean found among candidates: " + candidateBeans.keySet());
}
else if (candidateLocal && !primaryLocal) {
primaryBeanName = candidateBeanName;
}
}
else {
primaryBeanName = candidateBeanName;
}
}
if (primaryBeanName == null &&
(this.resolvableDependencies.values().contains(beanInstance) ||
matchesBeanName(candidateBeanName, descriptor.getDependencyName()))) {
fallbackBeanName = candidateBeanName;
}
}
return (primaryBeanName != null ? primaryBeanName : fallbackBeanName);
}
* Determine the primary autowire candidate in the given set of beans.
* @param candidateBeans a Map of candidate names and candidate instances
* that match the required type, as returned by {@link #findAutowireCandidates}
* @param descriptor the target dependency to match against
* @return the name of the primary candidate, or <code>null</code> if none found
*/
protected String determinePrimaryCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) {
String primaryBeanName = null;
String fallbackBeanName = null;
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
if (isPrimary(candidateBeanName, beanInstance)) {
if (primaryBeanName != null) {
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
if (candidateLocal == primaryLocal) {
throw new NoSuchBeanDefinitionException(descriptor.getDependencyType(),
"more than one 'primary' bean found among candidates: " + candidateBeans.keySet());
}
else if (candidateLocal && !primaryLocal) {
primaryBeanName = candidateBeanName;
}
}
else {
primaryBeanName = candidateBeanName;
}
}
if (primaryBeanName == null &&
(this.resolvableDependencies.values().contains(beanInstance) ||
matchesBeanName(candidateBeanName, descriptor.getDependencyName()))) {
fallbackBeanName = candidateBeanName;
}
}
return (primaryBeanName != null ? primaryBeanName : fallbackBeanName);
}
참고)
@Autowired is type-driven but it provides a fallback catch to inject bean by name. Use @Resource if you want to perform a bean lookup and injection based on name, alternatively @Autowired along with @Qualifier can work as well, even though it is more useful when grouping beans. http://www.spiritwalker-jiang.com/archive/2013/02/11/Understanding-Autowired-annation-in-Spring
This is documented in section 3.9.3:
For a fallback match, the bean name is considered a default qualifier value.
In other words, the default behaviour is as though you'd added @Qualifier("country")
to the setter method.
반응형
'emotional developer > detect-Java' 카테고리의 다른 글
proxy 방식 이해 (0) | 2014.06.25 |
---|---|
mybatis Illegal overloaded getter method (0) | 2014.05.12 |
ibatis iterate , mybatis foreach 동적쿼리 비교. (0) | 2014.04.30 |