Spring源码分析(三)@Autowired依赖注入源码分析
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()) {
// 注入的时候就是 Optional<OrderService> orderservice; 这个方法内部调用的也是doResolveDependency方法只是把返回结果封装成了Optional. orderservice.get()才能得到里面的实例 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,如果找到了就返回。