不清楚实例化bean、填充属性、初始化bean的顺序、做的事、执行了哪些扩展器的请看我以前写的这篇【十八】Spring IOC 总结之getBean主流程和各个扩展点总结
测试代码的注入方式是:直接在成员变量上用@AutoWired注解
先说重点
@Autowired在成员变量上的依赖注入是AutowiredAnnotationBeanPostProcessor来完成的
AutowiredAnnotationBeanPostProcessor处理依赖注入的整个流程概况来说就是下面三个最重要的东西来做的:
1.它实现了MergedBeanDefinitionPostProcessor,主要用到方法postProcessMergedBeanDefinition。该方法在实例化完成后调用。
该方法主要做的是:解析@Autowire注解生成注入元数据injectionMetadata。
解析出该类哪些filed和filedmethod需要依赖注入,然后放入injectionMetadataCache缓存中,待后面填充阶段的postProcessPropertyValues方法使用。
2.它继承了InstantiationAwareBeanPostProcessorAdapter,主要用到方法postProcessPropertyValues。该方法在填充阶段调用。
它根据前面解析出来的injectionMetadata来做真正的依赖注入。
3.它有个map是 Map<String, InjectionMetadata> injectionMetadataCache。key是哪个bean里面有成员需要依赖注入,这个例子中Key就是testController。value是InjectionMetadata,它保存的是该类哪些字段需要依赖注入。
在bean实例化后,例子中即是testController(它里面需要注入成员变量testService)实例化后,进入填充阶段前,会调用该方法
源码:
@Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { if (beanType != null) { InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); } }做了两件事
1.搜索该Bean内@Autowired注解的信息,生成InjectionMetadata需要依赖注入的元数据信息
2. 检查配置成员
做了2件事:
1.以testController(它里面需要注入成员变量testService)为KEY,在injectionMetadataCache找InjectionMetadata
那么,很不幸,第一次是找不到的。找到了就直接返回了
2.找不到那就要自己创建InjectionMetadata了,然后再放入injectionMetadataCache中。自己创建对应的方法就是源码里面的buildAutowiringMetadata方法
这里用了个双重锁机制。
做了4件事:
1.遍历这个类所有的Filed
获取带了@Autowire注解的filed,过滤掉static的filed,解析这些@Autowire是否为requird
2.便利这个类所有的filedmethod,找到哪些方法里面用了需要依赖注入的bean的,找到桥接方法。
如果桥接方法和method不同则直接返回。
找到哪些方法有@Autowire标签,过来静态方法,过滤参数数量为0的方法,注入set参数。
3.找到该类的父类继续前两步操作。
4.返回InjectionMetadata。
源码:
@Override public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException { //从缓存中得到该类需要依赖注入的元数据 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; }做了2件事:
1.从该类中得到需要依赖注入的元数据
2.调用metadata.inject方法执行依赖注入
循环调用AutowiredAnnotationBeanPostProcessor#inject进行依赖注入
@Override protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable { Field field = (Field) this.member; 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(); try { 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)) { if (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); } } }做了3件事:
1.解析依赖DefaultListableBeanFactory#beanFactory.resolveDependency
其实主要就是找到依赖。这里后面有空详细介绍,赶着出门买菜
2.注册依赖registerDependentBeans
实际上就是写入DefaultListableBeanFactory类的两个MAP中
dependentBeanMap,key是例子中的testServiceImpl,value数组是哪些bean依赖了它,这里的value数组中就只有testController
dependenciesForBeanMap,key是例子中的testController,value数组是testController依赖了哪些bean,这里的value数组就只有testServiceImpl
3.通过反射为属性赋值
源码:
@Override public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { // ParameterNameDiscovery用于解析方法参数名称 descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); // 1. Optional<T> if (javaUtilOptionalClass == descriptor.getDependencyType()) { return new OptionalDependencyFactory().createOptionalDependency(descriptor, requestingBeanName); } // 2. ObjectFactory<T>、ObjectProvider<T> else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) { return new DependencyObjectProvider(descriptor, requestingBeanName); } // 3. javax.inject.Provider<T> else if (javaxInjectProviderClass == descriptor.getDependencyType()) { return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName); } else { // 4. @Lazy Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary( descriptor, requestingBeanName); // 5. 正常情况 if (result == null) { result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); } return result; } }做了2件事:
1.初始参数名称发现
2.根据各种不同的依赖类型( Optional、延迟注入、懒加载)解析依赖并返回。
本场就就是走的最后的doResolvDependency
doResolvDependency源码:
public Object doResolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); try { // 1. 快速查找,根据名称查找。AutowiredAnnotationBeanPostProcessor用到 Object shortcut = descriptor.resolveShortcut(this); if (shortcut != null) { return shortcut; } // 2. 注入指定值,QualifierAnnotationAutowireCandidateResolver解析@Value会用到 Class<?> type = descriptor.getDependencyType(); Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { if (value instanceof String) { // 2.1 占位符解析 String strVal = resolveEmbeddedValue((String) value); BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); // 2.2 Spring EL 表达式 value = evaluateBeanDefinitionString(strVal, bd); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); // 2.3 类型转换 return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); } // 3. 集合依赖,如 Array、List、Set、Map。内部查找依赖也是使用findAutowireCandidates Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } // 4. 单个依赖查询 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); // 4.1 没有查找到依赖,判断descriptor.require if (matchingBeans.isEmpty()) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } return null; } String autowiredBeanName; Object instanceCandidate; // 4.2 有多个,如何过滤 if (matchingBeans.size() > 1) { // 4.2.1 @Primary -> @Priority -> 方法名称或字段名称匹配 autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); // 4.2.2 根据是否必须,抛出异常。注意这里如果是集合处理,则返回null if (autowiredBeanName == null) { if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { return descriptor.resolveNotUnique(type, 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(); } // 4.3 到了这,说明有且仅有命中一个 if (autowiredBeanNames != null) { autowiredBeanNames.add(autowiredBeanName); } // 4.4 descriptor.resolveCandidate实际上调用 getBean(autowiredBeanName, type)。 return (instanceCandidate instanceof Class ? descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate); } finally { ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); } }doResolveDependency 封装了依赖查找的各种情况:
1)快速查找: @Autowired 注解处理场景。AutowiredAnnotationBeanPostProcessor 处理 @Autowired 注解时,如果注入的对象只有一个,会将该 bean 对应的名称缓存起来,下次直接通过名称查找会快很多。
2)注入指定值:@Value 注解处理场景。QualifierAnnotationAutowireCandidateResolver 处理 @Value 注解时,会读取 @Value 对应的值进行注入。如果是 String 要经过三个过程:①占位符处理 -> ②EL 表达式解析 -> ③类型转换,这也是一般的处理过程,BeanDefinitionValueResolver 处理 String 对象也是这个过程。
3)集合依赖查询:直接全部委托给 resolveMultipleBeans 方法。
4) 单个依赖查询:先调用 findAutowireCandidates 查找容器中所有可用的依赖,如果有多个依赖,则根据规则匹配: @Primary -> @Priority -> ③方法名称或字段名称
而findAutowireCandidates的内部逻辑是:
1.先查找 Spring IoC 内部依赖 resolvableDependencies。
在 AbstractApplicationContext#prepareBeanFactory 方法中默认设置了如下内部依赖:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext。
2.在父子容器进行类型查找:查找类型匹配的 beanNames。
循环调用beanFactory#beanNamesForType 方法根据类型查找先匹配单例实例类型(包括 Spring 托管 Bean),再匹配 BeanDefinition 的类型。
这里可以看到 Spring 依赖注入的另外两个来源:一是 Spring 托管的外部 Bean,二是 Spring BeanDefinition。
3.补偿机制
如果依赖查找无法匹配,Spring 提供了两种补偿机制。
先使用泛型补偿,不允许自身引用补偿:即 fallbackDescriptor。此时如果是集合依赖,对象必须是 @Qualifier 类型。
允许泛型补偿和自身引用补偿:但如果是集合依赖,必须过滤自己本身,即 beanName.equals(candidate) 必须剔除。