Spring依赖注入(二)注入

类名:AutowiredAnnotationBeanPostProcessor
方法调用:postProcessProperties -> inject -> resolveFieldValue (属性注入)或者
postProcessProperties -> inject -> resolveMethodArguments (方法注入)

如果有@autowired、@inject、@value注解就会被spring认为是一个注入点,进行注入
先看字段注入resolveFieldValue 主要看resolveDependency方法
在这里插入图片描述
首先生成依赖描述器 DependencyDescriptor,作为参数传入resolveDependency中,会根据该依赖描述从BeanFactory中找出对应的唯一的一个Bean对象。

DefaultListableBeanFactory中**resolveDependency()**方法的具体实现,具体流程图:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

	@Override
	@Nullable
	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
		// 用来获取方法入参名字的
		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());

		// 所需要的类型是Optional
		if (Optional.class == descriptor.getDependencyType()) {
			return createOptionalDependency(descriptor, requestingBeanName);
		}
		// 所需要的的类型是ObjectFactory,或ObjectProvider
		else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) {
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		} else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
			return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
		} else {
			// 在属性或set方法上使用了@Lazy注解,那么则构造一个代理对象并返回,真正使用该代理对象时才进行类型筛选Bean
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);

			if (result == null) {
				// descriptor表示某个属性或某个set方法
				// requestingBeanName表示正在进行依赖注入的Bean
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}

首先获取入参的名字,descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
jdk1.7的反射是无法直接获取方法的参数名字的,1.8也需要一定的编译配置才行。
会产生两个发现器,为什么两个呢,防止反射拿不到
第一个基于反射
第二个基于字节码本地变量表分析
在这里插入图片描述
然后,根据不同的类型进行不同的处理,直接看else就行了
先判断属性上有没有lazy注解,方法参数前有没有lazy注解

// 在属性或set方法上使用了@Lazy注解,那么则构造一个代理对象并返回,真正使用该代理对象时才进行类型筛选Bean
	Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);

如果没有lazy注解,直接执行

			if (result == null) {
				// descriptor表示某个属性或某个set方法
				// requestingBeanName表示正在进行依赖注入的Bean
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}

下面看这个doResolveDependency方法

	@Nullable
	public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			// 如果当前descriptor之前做过依赖注入了,则可以直接取shortcut了,相当于缓存
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}

			Class<?> type = descriptor.getDependencyType();
			// 获取@Value所指定的值
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
				if (value instanceof String) {
					// 占位符填充(${})
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
					// 解析Spring表达式(#{})
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				// 将value转化为descriptor所对应的类型
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				try {
					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
				} catch (UnsupportedOperationException ex) {
					// A custom TypeConverter which does not support TypeDescriptor resolution...
					return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
				}
			}

			// 如果descriptor所对应的类型是数组、Map这些,就将descriptor对应的类型所匹配的所有bean方法,不用进一步做筛选了
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}

			// 找到所有Bean,key是beanName, value有可能是bean对象,有可能是beanClass
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				// required为true,抛异常
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;

			if (matchingBeans.size() > 1) {
				// 根据类型找到了多个Bean,进一步筛选出某一个, @Primary-->优先级最高--->name
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
					} else {
						// In case of an optional Collection/Map, silently ignore a non-unique case:
						// possibly it was meant to be an empty collection of multiple regular beans
						// (before 4.3 in particular when we didn't even look for collection beans).
						return null;
					}
				}
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			} else {
				// We have exactly one match.
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			// 记录匹配过的beanName
			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(autowiredBeanName);
			}
			// 有可能筛选出来的是某个bean的类型,此处就进行实例化,调用getBean
			if (instanceCandidate instanceof Class) {
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			if (result instanceof NullBean) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				result = null;
			}
			if (!ClassUtils.isAssignableValue(type, result)) {
				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
			}
			return result;
		} finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

根据类型找beanname的流程图
在这里插入图片描述
findAutowireCandidates流程图
在这里插入图片描述
在bytype到byname种经过了6层筛选
寻找注入点

包括方法和属性

先处理@value注解

然后根据类型把所有beanName找出来

在这里插入图片描述
看看这些bean的autowiredCandidate属性是否为true

在这里插入图片描述
再看这些属性是不是泛型如果是泛型,看看和真正的泛型是不是匹配

在这里插入图片描述
再看@qualifier属性是否匹配

如果还是筛选出多个,就看其中有没有上面有@primary注解的,如果有直接返回

如果没有再取name,最终才完成依赖注入

@Resource流程图
在这里插入图片描述
@Qualifier的使用

定义两个注解:

@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier("random")
public @interface Random {
}
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier("roundRobin")
public @interface RoundRobin {
}

定义一个接口和两个实现类,表示负载均衡:

public interface LoadBalance {
 String select();
}
@Component
@Random
public class RandomStrategy implements LoadBalance {

 @Override
 public String select() {
  return null;
 }
}
@Component
@RoundRobin
public class RoundRobinStrategy implements LoadBalance {

 @Override
 public String select() {
  return null;
 }
}

使用

@Component
public class UserService  {

 @Autowired
 @RoundRobin
 private LoadBalance loadBalance;

 public void test() {
  System.out.println(loadBalance);
 }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值