自动注入的流程:
Spring里面到底有几种依赖注入的方式呢?
1:手动注入
1)我们在xml文件中定义一个bean的时候,在bean标签下面使用<property name="bird" ref="bird"> 代码中提供set方法,把外部对象注入到bean中的方式就是属于手动注入,因为我们要手动的维护这个属性。
2)也可以在bean标签下面使用构造函数标签,来指定使用那个构造函数来向bean中注入属性。
2:自动注入
1)XML里面的自动注入
autowire可以选择 byType,byName, constructor default,no
----- byType
<bean id="people" class="com.my.ioc.pojo.People" autowire="byType"/>
<bean id="bird" class="com.my.ioc.pojo.factorybean.Bird" />
people里只提供了brid的set方法。
调用getBean(people)就可以得到注入bird的people实例,
这种自动注入,就是在填充people属性的时候获取set方法,发现set方法参数也是个bean的时候,就根据这个参数的类的类型来获取对应的bean,然后调用这个set方法,并把参数的bean实例传递进来赋值给当前的属性,完成自动注入。
---- byName
xml中填写的是byName的时候,这个name不是根据属性名,也不是set方法的参数名,而是set方法名,把set去掉之后剩下的首字母小写之后的内容作为beanName来找bean。
----constructor
构造方法就涉及到到构造方法的选择,选择的逻辑,分析源码的时候具体记录。
--- default
在xml的最上层有个beans标签,可以在那个里面定义default-autowire="byType" 属性,然后可以在下面定义具体的bean的时候用default值,就按照最上层的那个设置来,如果bean标签没有写autorie属性,也是默认按照default-autowire 指定的来。
-----no
就是不进行自动注入
上篇记录中有看到在填充属性的时候会从从BeanDefinition中获取这个属性值进行判断。
2) @Autowired的自动注入
注解可以用在的地方:方法,属性上,构造方法。如果使用xml来构造容器的话,这个注解默认是不生效的,需要在xml中开启注解: <context:annotation-config></context:annotation-config>
或者直接使用注解容器。AnnotationConfigApplicationContext
这个注解其实是上面xml中autowire属性的升级,
第一个升级的地方就是可以用在属性定义上面,而且注入的过程是先根据byType找到这个类是不是有多个类型,如果找到多个类型再根据属性名byName来找到bean。
第二个升级的地方就是这个注解可以用在方法上,但是不一定非要用在属性的set方法上,用在任意方法名都可以,只要方法参数是个bean。
自动注入使用到的后置处理器:AutowiredAnnotationBeanPostProcessor
上面两个标黄的接口和类,上篇实例化过程中提到了。其中的MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition 是在实例化后执行的一个后置处理器,而上面的这个实现类AutowiredAnnotationBeanPostProcessor
,就在这个方法逻辑里找到注入点进行解析。在 InstantiationAwareBeanPostProcessor.postProcessProperties 方法中进行实际的注入操作。
AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition
AutowiredAnnotationBeanPostProcessor继承了InstantiationAwareBeanPostProcessorAdapter重写了里面的postProcessProperties,在这个方法里把上面那个方法找到的注入点进行属性注入。
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// InjectionMetadata 中保存了所有被@Autowired注解标注的属性/方法 并封装成一个个的InjectedElement
// 在postProcessMergedBeanDefinition 方法里已经得到放到缓存中了
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//按注入点进行注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
先从怎么找到注入点的方法进行跟进。
会把一个bean的注入点封装成一个InjectionMetadata( new InjectionMetadata(clazz, elements))elements为所有的注入点。并缓存到this.injectionMetadataCache 一个Map中,key为beanName。
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
// 把beanName作为缓存的key
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
//寻找当前class的注入点,把所有注入点整合为一个InjectionMetadata
metadata = buildAutowiringMetadata(clazz);
//放入缓存中
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
buildAutowiringMetadata(clazz)
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
// 判断是不是候选者类,比如说类名是以 java.开头的则不是候选者类 Order的实现类也不是候选者类
// 但是如果this.autowiredAnnotationTypes 中有以java.开头的注解就返回true了
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 遍历属性,看是否有@Autowired @Value @Inject注解
ReflectionUtils.doWithLocalFields(targetClass, field -> {
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
//如果存在上面中的一个
if (ann != null) {
// 如果字段是静态的,则直接进行返回,不进行注入
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 是否required
boolean required = determineRequiredStatus(ann);
// 生成一个注入点AutowiredFieldElement
currElements.add(new AutowiredFieldElement(field, required));
}
});
//遍历所有的方法 看是否有@Autowired @Value @Inject注解
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
// 这是找字节码中被桥接后的方法
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
//静态方法不能用来注入属性
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
//方法参数为0 不能用来注入属性
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
// 是会去找父类 进行递归操作
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
这个方法首先会判断当前类是否为候选者。this.autowiredAnnotationTypes 中存着可以被识别为注入点的注解:Inject只有在项目中存在的时候才会添加进来,如果没有报错也不会处理。
候选者的判断条件:
public static boolean isCandidateClass(Class<?> clazz, Collection<Class<? extends Annotation>> annotationTypes) {
for (Class<? extends Annotation> annotationType : annotationTypes) {
if (isCandidateClass(clazz, annotationType)) {
return true;
}
}
return false;
}
public static boolean isCandidateClass(Class<?> clazz, String annotationName) {
// 注解有java开头的注解就算是候选者,但是一般不会有,除非自己添加
if (annotationName.startsWith("java.")) {
return true;
}
// 如果clazz是以java.开头或Order的子类,也不算是候选者
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
return false;
}
return true;
}
static boolean hasPlainJavaAnnotationsOnly(Class<?> type) {
return (type.getName().startsWith("java.") || type == Ordered.class);
}
判断它是候选者之后,找到候选者中所有的注入点,分为属性和方法。
1:遍历属性,查看属性上面是否有上面说的三种注解的其中之一,有的话就返回。
@Nullable
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
// 查看当前字段上是否存在@Autowired @Value @Inject注解 存在其中一个则返回,表示可以注入
MergedAnnotations annotations = MergedAnnotations.from(ao);
// autowiredAnnotationTypes 是一个LinkHashSet 所以会按照顺序去判断当前字段中是否有Autowired注解,如果有则返回,
//如果没有则Autowired注解 则判断是否有value注解 再判断是否有Inject注解
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
MergedAnnotation<?> annotation = annotations.get(type);
if (annotation.isPresent()) {
return annotation;
}
}
return null;
}
请注意,上面属性注入点,生成的 InjectionMetadata.InjectedElement的子类 AutowiredFieldElement来存储。
2:找方法中的注入点,这里找的是被桥接后的注入点。关于什么是桥接方法,https://blog.csdn.net/mhmyqn/article/details/47342577
方法的注入点用 InjectionMetadata.InjectedElement的子类 AutowiredMethodElement 来存储。
把两中element放入elements 中,
最后调用InjectionMetadata.forElements(elements, clazz); 生成InjectionMetadata返回。
public static InjectionMetadata forElements(Collection<InjectedElement> elements, Class<?> clazz) {
return (elements.isEmpty() ? InjectionMetadata.EMPTY : new InjectionMetadata(clazz, elements));
}
AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition 找到注入点之后。就 在AutowiredAnnotationBeanPostProcessor.postProcessProperties 方法进行注入。
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// InjectionMetadata 中保存了所有被@Autowired注解标注的属性/方法 并封装成一个个的InjectedElement
// 在postProcessMergedBeanDefinition 方法里已经得到放到缓存中了
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//按注入点进行注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
//遍历每个能够注入的属性 进行注入
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
// element可能是Method 也可能是Field 会走不同的子类 AutowiredFieldElement AutowiredMethodElement 都在AutowiredAnnotationBeanPostProcessor 内部
element.inject(target, beanName, pvs);
}
}
}
属性注入点注入的的逻辑,AutowiredFieldElement.inject
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
// 当前注入点已经注入过了 有缓存了 则利用缓存this.cachedFieldValue找到对应的bean
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
//spring在真正查找属性对应的对象之前 会先将该属性的描述封装成一个DependencyDescriptor 里面存了Field
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// 根据field去寻找合适的bean
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
// 这里才是真正的赋值操作
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
第一次注入属性,会执行:value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
找到属性对应的bean。 DefaultListableBeanFactory.resolveDependency,
//只负责找对象返回出去,赋值时在外面进行的,比如如果时@Value(xxx) 就把xxx返回出去
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// DependencyDescriptor 表示一个依赖,可以是一个字段,可以是一个属性字段,可能是一个构造方法参数,可能是一个set方法参数
//根据descriptor去BeanFactory中找到bean
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
//如果依赖类型是Optional
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
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 {
//在使用@Autowired 注解时 也可以使用@Lazy注解,到时候注入的会是一个代理对象
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
//通过解析descriptor找到bean对象
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
先看主要获取实例的方法: doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); 自动注入的逻辑最主要逻辑就是找到注入的对象,这个方法就是处理这个逻辑的:
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
//1: 如果DepenDencyDescriptor是一个 ShortcutDependencyDescriptor
// 那么 会直接理解成beanName从beanfactoryz中拿到一个bean
//在利用@autowired注解来进行依赖注入时会利用shortcutDependencyDescriptor来进行依赖注入的缓存
//表示当解析完某个依赖信息后 会把依赖的bean的beanName缓存起来
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
//获取descriptor具体的类型 某个Filed的类型 或者某个方法参数的类型
Class<?> type = descriptor.getDependencyType();
// 2:如果descriptor上有@Value注解 获取@Value注解中所配置的值 这个resolver是 QualifierAnnotationAutowireCandidateResolver
// AutowireCandidateResolver autowireCandidateResolver = SimpleAutowireCandidateResolver.INSTANCE; 这是默认的resolver,它可以判断某个bean是不是一个自动注入的候选bean
// 比如: xml中定义的bean可以写个 autowire-candidate="false" 把bean排除 不是自动装配的bean
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
// 先进行占位符的填充,解析$符号 $(xxx) spring会从环境变量中获取xxx对应的value进行填充
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
// 解析Spring EL表达式 解析# 符号 (可以进行运算 可以写某个bean的名字)
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
// 使用类型转换器,转换@Value得到的字符串到type类型
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()));
}
}
// 没有使用@Value注解
//3:要注入的类型是不是一个Map,collection
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//4: 表示会根据type去找bean,Map的key为beanName,Map 的value为对象 (注意可能是bean对象 也可能是某个bean的class对象,因为该方法只负责根据类型找到对应的bean,
// 如果该bean 还没有实例化,那么就返回bean对应的class对象
// 该方法也不负责实例化,只返回该bean对应的Class对象,表示这个Bean也是结果之一)
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
// 如果根据类型没有找到bean 如果时必须的则抛出异常 如果不是必须的则直接返回 null
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
//如果找到多个,根据其它参数确定一个返回 {@code @Primary} and {@code @Priority} (in that order)
if (matchingBeans.size() > 1) {
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();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
//如果返回的是Class类型就从beanFactory中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);
}
}
第一步先判断 descriptor是不是具体的类型,ShortcutDependencyDescriptor 说明已经处理过了,直接从工厂中获取。
第二步,先判断的注解是@Value, 如果存在这个注解就解析,如果解析出来的值能找到类型转换器进行转换,就把结果返回出去。
第三步,判断是不是map和集合的类型,如果是的话就返回相对应的类型实例。
第四步,如果上面都没匹配到结果,就根据类型找到这个的类型的相关bean,封装成一个map返回,Map的key为beanName,Map 的value为对象 (注意可能是bean对象 也可能是某个bean的class对象)
找到候选者bean的逻辑: findAutowireCandidates
// 根据requiredType 找到自动匹配的候选者bean
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
// Ancestors 是祖先的意思,这个方法是根据requiredType去当前以及祖先的beanFactory中找这个类型的beanName
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
// 先从 resolvableDependencies 中
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
// requiredType 是autowiringType的子类
//requiredType 类是不是继承或实现了autowiringType,autowiringType为父类或接口,子类对象可以赋值给父类属性
if (autowiringType.isAssignableFrom(requiredType)) {
// 是resolvableDependencies中子类所存的对象
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
//把 resolvableDependencies中保存的对象作为当前属性的一个候选者
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
// 对候选者bean进行过滤,首先候选者不是自己,然后候选者是支持自动注入给其它beand的
for (String candidate : candidateNames) {
// isAutowireCandidate方法中会去判断候选者是否和descriptor匹配 并不是所有bean都是可以进行注入的
// 如果isAutowireCandidate返回的false,也是不会把它作为候选者beanName
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty()) {
boolean multiple = indicatesMultipleBeans(requiredType);
// Consider fallback matches if the first pass failed to find anything...
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty() && !multiple) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
返回候选者的map之后,如果这个map为空,则直接返回方法结束,如果map中只有一个候选者,那就是需要注入的值就是这个map的value值了。
但是如果Map中有多个候选者,就要从这些候选者中筛选出一个唯一的一个候选者返回。
筛选唯一beanName的方法是:determineAutowireCandidate 。就是判断这个候选者的bean上是否有@Primary @Priority(注意是有顺序的) ,如果都没有就 根据属性名/方法参数名确定,找到的candidateName 和当前descriptor.getDependencyName 相等就返回
@Nullable
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
// 取@Primary 的bean
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
// 取优先级最高的bean,通过@Priority来定义优先级 数字越小 优先级越高
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
// 如果根据上面的 @Primary @Priorityd都没找到,就根据属性名/方法参数名从map中获取一个候选beanName
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
// 根据属性名/方法参数名确定,找到的candidateName 和当前descriptor.getDependencyName 相等就返回
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
根据 找到的autowiredBeanName 从map获取到 instanceCandidate,上面提到过这个实例候选者不一定就是需要注入的对象,可能是Class对象,如果是Class对象,就从beanFactory中获取对象的bean对象返回。
在上面找候选者bean的方法 findAutowireCandidates 是一段很重要的逻辑,里面有怎么根据type找到对应的所有的beanName(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager())), 以及怎么判断找到的这些bean是不是可以作为候选者bean(方法isAutowireCandidate)。
根据类型找到所有的beanName, 就是遍历所有的beanDefinition看对应的类型是不是和type匹配,当然这个过程设计到很多逻辑,因为beanDefinition类型太多了,这里不展开讲了。
根据类型找到的这些beanName还不能直接返回,还要判断是不是可以作为候选者beanName, 这里我们上面提到过,有一个 autowire-candidate 属性如果是false,表示这个bean不能作为候选者让其它bean注入。
isAutowireCandidate 方法我们点进去看:
1: 2:
3: 在第三个方法中,才调用真正判断是否为候选者。实现类是 QualifierAnnotationAutowireCandidateResolver。
1:QualifierAnnotationAutowireCandidateResolver# isAutowireCandidate
首先调用父类的 isAutowireCandidate 方法,如果父类匹配的上再进行自己逻辑的判断,如果父类都不过,则直接false。
2:父类1 GenericTypeAwareAutowireCandidateResolver# isAutowireCandidate
3:父类2 SimpleAutowireCandidateResolver# isAutowireCandidate
到这里才是判断 autowire-candidate 属性是否为true的,也就是首先判断这个属性是否为true,如果为false,则这个bean直接认为不是候选者。但是为true了,这个bean也不一定是候选者,还有其它判断。
回到父类2中。如果父类3返回true了,执行自己的判断逻辑: checkGenericTypeMatch(bdHolder, descriptor); 这是泛型匹配,也就是注入点可以是泛型。举个例子:
public class Father<T> {
@Autowired
private T t;
public T getT() {
return t;
}
}
@Service
public class Son extends Father<People> {
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
System.out.println("======================");
Son son=(Son)applicationContext.getBean("son");
System.out.println(son.getT());
上面的结果是People可以正常被注入到t上面的。
注意如果注入点是个泛型,在上面 findAutowireCandidates 把所有的beanName都找出来了,挨个遍历找到和泛型类型匹配的类型bean。
如果没有泛型,这个父类2就返回true了。
走到QualifierAnnotationAutowireCandidateResolver 中的逻辑。这个类自己的逻辑就是匹配@Qualifier注解的。关于这个注解的作用参考:https://www.cnblogs.com/krock/p/14820404.html
总结:
对于@Autowired ,@Value,@Inject注解标识的注入点,注入的流程:
1:根据注解找到注入点
2:根据注入点进行注入,首先判断的是@Value,如果有@Value注解,就把注解中配置的属性值解析进行注入,这里会有类型转换。
3: 如果没有@Value注解,就先byType,再byName的方式找到唯一的bean进行注入。
4:byType会找到很多类型的beanName出来,先byType到byName中间会经过6步筛选:
1)判断是否为候选者isAutowireCandidate是否为true
2)如果是候选者,判断是否注入点的类型是泛型,如果是泛型执行GenericTypeAwareAutowireCandidateResolver中的逻辑
3)判断注入点是否使用了@Qualifier 注解,如果使用了执行QualifierAnnotationAutowireCandidateResolver 的匹配逻辑
经过上面的三步,得到一个Map<beanName, 对象(bean实例或者bean相应的Class对象)>,这个Map中数据可能是多个
4)继续筛选Map中的beanName,判断,beanName对应的bean上面是否有 @Primary注解,如果有的话,直接用这个beanName对应的value值。
5) 如果没有@Primary,判断bean上面是否有@Priority(1/2/3) 优先级,值越小优先级越高。
6)如果上面都没能唯一确认一个bean, 就根据注入点的属性名或方法参数名从Map看是否有对应的key,如果找到了就返回。