spring-context注解源码系列九——@Primary

注解说明

Indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency. If exactly one ‘primary’ bean exists among the candidates, it will be the autowired value.
在spring根据类型进行注入或者寻找Bean的时候,如果存在多个可注入对象,即该类型有多个Bean的时候,被@Primary标记的Bean会成为最终被选择的那个,当然,如果这些对象里面有超过1个Bean被@Primary标记,则会抛出异常。

使用示例

 @Component
 public class FooService {
 
     private FooRepository fooRepository;

     @Autowired
     public FooService(FooRepository fooRepository) {
     	 // 被注入的对象是 HibernateFooRepository 
         this.fooRepository = fooRepository;
     }
 }

 @Component
 public class JdbcFooRepository extends FooRepository {

     public JdbcFooRepository(DataSource dataSource) {
         // ...
     }
 }

 @Primary
 @Component
 public class HibernateFooRepository extends FooRepository {

     public HibernateFooRepository(SessionFactory sessionFactory) {
         // ...
     }
 }

相关源码

AnnotationConfigUtils

	/**
	 * 解析beanDefinition的附加的一些通用注解
	 */
	static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
		......

		// 如果存在@Primary,则设置BeanDefinition的primary属性
		if (metadata.isAnnotated(Primary.class.getName())) {
			abd.setPrimary(true);
		}
		
		......
	}

DefaultListableBeanFactory

/**
	 * Determine the primary candidate in the given set of beans.
	 * @param candidates a Map of candidate names and candidate instances
	 * (or candidate classes if not created yet) that match the required type
	 * @param requiredType the target dependency type to match against
	 * @return the name of the primary candidate, or {@code null} if none found
	 * @see #isPrimary(String, Object)
	 * 从候选列表里面找到的primary(主要)的那个bean
	 */
	@Nullable
	protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
		String primaryBeanName = null;
		for (Map.Entry<String, Object> entry : candidates.entrySet()) {
			String candidateBeanName = entry.getKey();
			Object beanInstance = entry.getValue();
			// 根据BeanName判断是否是primary(主要的)
			if (isPrimary(candidateBeanName, beanInstance)) {
				if (primaryBeanName != null) {
					// 如果当前已经存在一个primaryBean的情况,又找到了一个新的,
					// 则根据2个Bean是否是本地的(当前bean工厂是否包含对应的beanName)来进一步判断
					// 如果2个都是本地的,则直接保异常
					// 如果新的那个1个是本地的,1个不是,则保留本地那个
					// 如果2个都不是,则保持不变
					boolean candidateLocal = containsBeanDefinition(candidateBeanName);
					boolean primaryLocal = containsBeanDefinition(primaryBeanName);
					if (candidateLocal && primaryLocal) {
						throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
								"more than one 'primary' bean found among candidates: " + candidates.keySet());
					}
					else if (candidateLocal) {
						primaryBeanName = candidateBeanName;
					}
				}
				else {
					primaryBeanName = candidateBeanName;
				}
			}
		}
		return primaryBeanName;
	}
/**
	 * Return whether the bean definition for the given bean name has been
	 * marked as a primary bean.
	 * @param beanName the name of the bean
	 * @param beanInstance the corresponding bean instance (can be null)
	 * @return whether the given bean qualifies as primary
	 * 根据给定的BeanName判断一个Bean是否是一个主要的Bean
	 */
	protected boolean isPrimary(String beanName, Object beanInstance) {
		// 如果当前存在BeanName对应的BeanDefinition,则根据合并后的BeanDefinition判断是否是主要的
		if (containsBeanDefinition(beanName)) {
			return getMergedLocalBeanDefinition(beanName).isPrimary();
		}
		// 如果当前不存在,则从父工厂寻找并判断
		BeanFactory parent = getParentBeanFactory();
		return (parent instanceof DefaultListableBeanFactory &&
				((DefaultListableBeanFactory) parent).isPrimary(beanName, beanInstance));
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值