根据类型自动装配:
首先得到 所有需要装配的非简单属性 ,(不是字符串等简单类型)也就是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 可以对成员变量、方法以及构造函数进行注释。我们在日常开发的过程中主要使用的是对成员变量的自动装配,即先使用默认构造器创建实例之后,再通过注解使用setter注入属性。
由上文可知,实现@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缓存中获取),进行属性注入。方法包括了:
findAutowiringMetadata在Bean中找到所有@Autowire注解的元数据checkConfigMembers检查元数据中的信息目标元数据使用缓存存储,关键的解析注解生成元数据的方法是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 中,以供真正的属性注入时使用。
遍历上一步中Elements属性,将其注册到BeanDefinition的 externallyManagedConfigMembers,checkedElements 属性中以供后续使用。
此方法中包括了:
findAutowiringMetadata找到所有的@Autowire注解的元数据inject属性注入此方法中:遍历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主要是通过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类型的情况可以很清晰地看到选择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时,会再按照属性名进行筛选。