Spring IOC(五)resolveDependency方法源码分析(byType、@Autowire自动装配)

    技术2023-12-19  68

    目录

    byType源码分析@Autowired注解自动装配过程使用方式抛出问题 @Autowired源码分析第1步:MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition源码分析第1-1步:findAutowiringMetadata在Bean中找到所有@Autowire注解的元数据第1-2步:checkConfigMembers检查元数据中的信息 第2步:InstantiationAwareBeanPostProcessor#postProcessPropertyValues第2-1步:findAutowiringMetadata找到所有的@Autowire注解的元数据(从injectionMetadataCache缓存获取)第2-2步:inject属性注入 resolveDependency方法第1步:findAutowireCandidates,通过Type在工厂中找到所有的候选Bean第3步:Type为普通类型,根据符合的Bean个数做处理第3-3步:determineAutowireCandidate在多个候选Bean中选择 总结

    byType源码分析

    protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } Set<String> autowiredBeanNames = new LinkedHashSet<String>(4); String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { try { PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName); // Don't try autowiring by type for type Object: never makes sense, // even if it technically is a unsatisfied, non-simple property. if (Object.class != pd.getPropertyType()) { MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd); // Do not allow eager init for type matching in case of a prioritized post-processor. boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass()); DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter); if (autowiredArgument != null) { pvs.add(propertyName, autowiredArgument); } for (String autowiredBeanName : autowiredBeanNames) { registerDependentBean(autowiredBeanName, beanName); if (logger.isDebugEnabled()) { logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" + propertyName + "' to bean named '" + autowiredBeanName + "'"); } } autowiredBeanNames.clear(); } } catch (BeansException ex) { throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex); } } }

    根据类型自动装配:

    首先得到 所有需要装配的非简单属性 ,(不是字符串等简单类型)也就是Bean类型的属性,并返回检查此属性的set方法,存在的时候才可自动装配创建一个AutowireByType类型的依赖描述符resolveDependency:解析依赖关系 ,返回依赖的Bean实例,这个方法在本篇最后分析。保存返回的依赖Bean实例:pvs.add(propertyName, autowiredArgument)记录依赖关系(最后将在applyPropertyValues中实现pvs中的属性注入)

    注意,其中有一行DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);

    /** * Special DependencyDescriptor variant for Spring's good old autowire="byType" mode. * Always optional; never considering the parameter name for choosing a primary candidate. */ @SuppressWarnings("serial") private static class AutowireByTypeDependencyDescriptor extends DependencyDescriptor { public AutowireByTypeDependencyDescriptor(MethodParameter methodParameter, boolean eager) { super(methodParameter, false, eager); } @Override public String getDependencyName() { return null; } }

    表示byType形式的依赖描述符有一种特殊的表示: 在选择主要候选对象时从不考虑参数名称! 这句话什么意思呢,就是使用byType形式的自动装配,当此Type的Bean有多个时,将会直接抛出错误,而不是再根据参数的Name去匹配第二遍。 主要是与@Autowired形式的属性注入的特点形成对比,具体分析如下。

    @Autowired注解自动装配过程

    @Autowired 可以对成员变量、方法以及构造函数进行注释。我们在日常开发的过程中主要使用的是对成员变量的自动装配,即先使用默认构造器创建实例之后,再通过注解使用setter注入属性。

    使用方式

    @Component public class Cat { public String toString() { return "miao"; } } @Component public class Animal { @Autowired private Cat cat; public Cat getCat() { return this.cat; } public void setCat(Cat cat) { this.cat = cat; } } public class MainTest { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("spring/applicationContext.xml"); Animal animal = ac.getBean(Animal.class); System.out.println(animal.getCat().toString()); } } <context:component-scan base-package="*"/>

    抛出问题

    由上文可知,实现@Autowire类型属性注入的后处理器是AutowiredAnnotationBeanPostProcessor,该接口继承了InstantiationAwareBeanPostProcessor,实现了postProcessPropertyValues方法。

    AutowiredAnnotationBeanPostProcessor何时被注册? 当解析xml配置文件的<context:component-scan />标签时,会将AutowiredAnnotationBeanPostProcessor注册到工厂。AutowiredAnnotationBeanPostProcessor何时被调用? 对于@Autowire注解的属性注入,在整个Bean的属性填充中分为两个步骤: 1. 注解的解析 在Spring(四)doCreateBean方法源码分析的第2步:当创建完初始实例之后 ,会进行applyMergedBeanDefinitionPostProcessors:获取全部的MergedBeanDefinitionPostProcessor,然后遍历执行其postProcessMergedBeanDefinition方法。这个方法的意义为对MergedBeanDefinition进行修改,即对 bean定义 进行后期处理。 AutowiredAnnotationBeanPostProcessor继承了MergedBeanDefinitionPostProcessor,在AutowiredAnnotationBeanPostProcessor中的实现即为:对@Autowire注解的Field及Method进行解析,并放入 injectionMetadataCache缓存 中。 2. 属性的注入 在Spring(四)doCreateBean方法源码分析中的第4-3步:InstantiationAwareBeanPostProcessor.postProcessPropertyValues。 AutowiredAnnotationBeanPostProcessor继承了InstantiationAwareBeanPostProcessor,在AutowiredAnnotationBeanPostProcessor中的实现即为:找到被Autowired注解的属性(从injectionMetadataCache缓存中获取),进行属性注入。

    @Autowired源码分析

    第1步:MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition源码分析

    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { if (beanType != null) { InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); } }

    方法包括了:

    findAutowiringMetadata在Bean中找到所有@Autowire注解的元数据checkConfigMembers检查元数据中的信息

    第1-1步:findAutowiringMetadata在Bean中找到所有@Autowire注解的元数据

    private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) { // Fall back to class name as cache key, for backwards compatibility with custom callers. 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); } try { metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); } catch (NoClassDefFoundError err) { throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() + "] for autowiring metadata: could not find class that it depends on", err); } } } } return metadata; }

    目标元数据使用缓存存储,关键的解析注解生成元数据的方法是buildAutowiringMetadata:

    private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>(); Class<?> targetClass = clazz; do { final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<InjectionMetadata.InjectedElement>(); ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() { @Override public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { AnnotationAttributes ann = findAutowiredAnnotation(field); if (ann != null) { if (Modifier.isStatic(field.getModifiers())) { if (logger.isWarnEnabled()) { logger.warn("Autowired annotation is not supported on static fields: " + field); } return; } boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } } }); ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() { @Override public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { if (logger.isWarnEnabled()) { logger.warn("Autowired annotation is not supported on static methods: " + method); } return; } if (method.getParameterTypes().length == 0) { if (logger.isWarnEnabled()) { logger.warn("Autowired annotation should 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 new InjectionMetadata(clazz, elements); }

    关注上半部分,doWithLocalFields,找到Bean中带有注解的属性。其中的findAutowiredAnnotation是通过匹配注解找属性的方法。 找到之后进行两个操作:

    判断属性是否是Static,如果是静态的,则抛出错误判断属性是否是required,将Required与Field一起包装成AutowiredFieldElement返回

    最后将找到的被注解Field存入到 injectionMetadataCache 中,以供真正的属性注入时使用。

    第1-2步:checkConfigMembers检查元数据中的信息

    public void checkConfigMembers(RootBeanDefinition beanDefinition) { Set<InjectedElement> checkedElements = new LinkedHashSet<InjectedElement>(this.injectedElements.size()); for (InjectedElement element : this.injectedElements) { Member member = element.getMember(); if (!beanDefinition.isExternallyManagedConfigMember(member)) { beanDefinition.registerExternallyManagedConfigMember(member); checkedElements.add(element); if (logger.isDebugEnabled()) { logger.debug("Registered injected element on class [" + this.targetClass.getName() + "]: " + element); } } } this.checkedElements = checkedElements; }

    遍历上一步中Elements属性,将其注册到BeanDefinition的 externallyManagedConfigMembers,checkedElements 属性中以供后续使用。

    第2步:InstantiationAwareBeanPostProcessor#postProcessPropertyValues

    public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex); } return pvs; }

    此方法中包括了:

    findAutowiringMetadata找到所有的@Autowire注解的元数据inject属性注入

    第2-1步:findAutowiringMetadata找到所有的@Autowire注解的元数据(从injectionMetadataCache缓存获取)

    第2-2步:inject属性注入

    public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable { Collection<InjectedElement> elementsToIterate = (this.checkedElements != null ? this.checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { boolean debug = logger.isDebugEnabled(); for (InjectedElement element : elementsToIterate) { if (debug) { logger.debug("Processing injected element of bean '" + beanName + "': " + element); } element.inject(target, beanName, pvs); } } }

    此方法中:遍历BeanDefinition中解析到的checkedElements,依次进行element.inject(target, beanName, pvs); Field类型的Element会进入到AutowiredFieldElement.inject方法:

    protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable { Field field = (Field) this.member; try { Object value; if (this.cached) { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } else { DependencyDescriptor desc = new DependencyDescriptor(field, this.required); desc.setContainingClass(bean.getClass()); Set<String> autowiredBeanNames = new LinkedHashSet<String>(1); TypeConverter typeConverter = beanFactory.getTypeConverter(); value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); 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)) { if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { this.cachedFieldValue = new RuntimeBeanReference(autowiredBeanName); } } } } else { this.cachedFieldValue = null; } this.cached = true; } } } if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } } catch (Throwable ex) { throw new BeanCreationException("Could not autowire field: " + field, ex); } }

    根据@Autowire注解装配:

    首先 在缓存中找到所有被@Autowire注解的属性创建一个依赖描述符resolveDependency:解析依赖关系 ,返回依赖的Bean实例记录依赖关系在此处直接通过 反射 给Bean的属性赋值

    注意,这种依赖描述符无特殊处理,getDependencyName会返回Filed的名字,默认实现:

    /** * Determine the name of the wrapped parameter/field. * @return the declared name (never {@code null}) */ public String getDependencyName() { return (this.field != null ? this.field.getName() : this.methodParameter.getParameterName()); }

    resolveDependency方法

    resolveDependency主要是通过Type类型,来解析依赖关系。用于byType类型的自动装配、@Autowired注解方式的自动装配。 resolveDependency方法中的核心步骤doResolveDependency:

    public Object doResolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { Class<?> type = descriptor.getDependencyType(); 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); value = evaluateBeanDefinitionString(strVal, bd); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); } if (type.isArray()) { Class<?> componentType = type.getComponentType(); DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor); targetDesc.increaseNestingLevel(); Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, targetDesc); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor); } return null; } if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); Object result = converter.convertIfNecessary(matchingBeans.values(), type); if (getDependencyComparator() != null && result instanceof Object[]) { Arrays.sort((Object[]) result, adaptDependencyComparator(matchingBeans)); } return result; } else if (Collection.class.isAssignableFrom(type) && type.isInterface()) { Class<?> elementType = descriptor.getCollectionType(); if (elementType == null) { if (descriptor.isRequired()) { throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]"); } return null; } DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor); targetDesc.increaseNestingLevel(); Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, targetDesc); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor); } return null; } if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); Object result = converter.convertIfNecessary(matchingBeans.values(), type); if (getDependencyComparator() != null && result instanceof List) { Collections.sort((List<?>) result, adaptDependencyComparator(matchingBeans)); } return result; } else if (Map.class.isAssignableFrom(type) && type.isInterface()) { Class<?> keyType = descriptor.getMapKeyType(); if (String.class != keyType) { if (descriptor.isRequired()) { throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() + "] must be [java.lang.String]"); } return null; } Class<?> valueType = descriptor.getMapValueType(); if (valueType == null) { if (descriptor.isRequired()) { throw new FatalBeanException("No value type declared for map [" + type.getName() + "]"); } return null; } DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor); targetDesc.increaseNestingLevel(); Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, targetDesc); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor); } return null; } if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } return matchingBeans; } else { Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(type, "", descriptor); } return null; } if (matchingBeans.size() > 1) { String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (primaryBeanName == null) { throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet()); } if (autowiredBeanNames != null) { autowiredBeanNames.add(primaryBeanName); } return matchingBeans.get(primaryBeanName); } // We have exactly one match. Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); if (autowiredBeanNames != null) { autowiredBeanNames.add(entry.getKey()); } return entry.getValue(); } }

    方法很长,包括如下功能:

    findAutowireCandidates,找到 所有匹配Type的所有Bean ,返回matchingBeans:一个Map<String, Object>如果属性的类型是「数组、集合、Map」,只要matchingBeans不为空则直接返回重点看依赖是普通Bean类型的情况

    第1步:findAutowireCandidates,通过Type在工厂中找到所有的候选Bean

    protected Map<String, Object> findAutowireCandidates( String beanName, Class<?> requiredType, DependencyDescriptor descriptor) { String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this, requiredType, true, descriptor.isEager()); Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length); for (Class<?> autowiringType : this.resolvableDependencies.keySet()) { if (autowiringType.isAssignableFrom(requiredType)) { Object autowiringValue = this.resolvableDependencies.get(autowiringType); autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType); if (requiredType.isInstance(autowiringValue)) { result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue); break; } } } for (String candidateName : candidateNames) { if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) { result.put(candidateName, getBean(candidateName)); } } if (result.isEmpty()) { DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch(); for (String candidateName : candidateNames) { if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, fallbackDescriptor)) { result.put(candidateName, getBean(candidateName)); } } } return result; }

    第3步:Type为普通类型,根据符合的Bean个数做处理

    Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(type, "", descriptor); } return null; } if (matchingBeans.size() > 1) { String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (primaryBeanName == null) { throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet()); } if (autowiredBeanNames != null) { autowiredBeanNames.add(primaryBeanName); } return matchingBeans.get(primaryBeanName); } // We have exactly one match. Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); if (autowiredBeanNames != null) { autowiredBeanNames.add(entry.getKey()); } return entry.getValue(); 如果matchingBeans(即工厂中此Type的Bean)是空,而属性又是Required,则抛出错误;如果matchingBeans正好为1个,则将此matchingBean加入到autowiredBeanNames中返回;如果matchingBeans有多个,determineAutowireCandidate在多个候选Bean中选择一个,选择的策略为determineAutowireCandidate

    第3-3步:determineAutowireCandidate在多个候选Bean中选择

    protected String determineAutowireCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) { Class<?> requiredType = descriptor.getDependencyType(); String primaryCandidate = determinePrimaryCandidate(candidateBeans, requiredType); if (primaryCandidate != null) { return primaryCandidate; } String priorityCandidate = determineHighestPriorityCandidate(candidateBeans, requiredType); if (priorityCandidate != null) { return priorityCandidate; } // Fallback for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) { String candidateBeanName = entry.getKey(); Object beanInstance = entry.getValue(); if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) || matchesBeanName(candidateBeanName, descriptor.getDependencyName())) { return candidateBeanName; } } return null; }

    可以很清晰地看到选择Bean的策略为:

    找加了@Primary注解的bean;找加了@Priority注解的bean;根据属性的名称和Spring中的beanName是否相等来判断; 如果上述三个方法都不能确定唯一的Bean,则会抛出异常 在第三种情况中,判断两个name是否相等的代码: matchesBeanName(candidateBeanName, descriptor.getDependencyName())

    注意:byType类型的descriptor.getDependencyName(),上文已经说明,被重写为return null;所以byType类型的自动装配无论名字是否相同,最后都将返回空,也就是抛出错误:NoUniqueBeanDefinitionException。

    所以说,@Autowired注解是先根据类型注入,当碰到多个相同类型时,就会根据属性名注入 。

    总结

    byType与Autowired注解是有些相似之处的

    它们的本质都是通过Type找到所有符合条件的Bean,然后再进行筛选。

    不同之处在于

    byType类型的自动装配是我们在xml中配置的属性标签所声明,在xml配置解析的过程中已经被解析到了BeanDefintion中;而@Autowired是一个注解,只能使用 后置处理器去解析注解 属性,进行处理。byType类型的自动装配通过resolveDependency找到所依赖的Bean对象之后,会存入到PropertyValues中,等到属性填充方法populateBean的最后applyPropertyValues时再统一的应用;而@Autowired通过resolveDependency找到所依赖的Bean对象之后,会直接通过反射将属性赋值,而不再存入PropertyValues。byType类型不会对属性名称进行判断;而@Autowired当找到有多个此类型的Bean时,会再按照属性名进行筛选。
    Processed: 0.021, SQL: 10