之前的源码阅读中,我们已经将spring创建bean的大致流程进行了了解,但大脑里依旧充满了各式各样的疑惑,这次我们更深一层去了解spring是如何进行属性注入的。
之前在说明依赖注入的时候其实提到属性注入的方法populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw),spring保持了一贯作风,这个方法并没有实际对属性进行注入,依旧是一些前置的判断和后置的处理,既然是学习还是很有必要了解前因后果的,一起来仔细的阅读一下源码吧。
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {//对bean的持有对象做一个空判断,既然都到了注入属性值的时候了,持有对象肯定不可以是空的if (bw == null) {//判断RootBeanDefinition中是否有MutablePropertyValues实例,MutablePropertyValues提供了对属性的读写操作实现,同时可以通过调用构造函数进行深度拷贝if (mbd.hasPropertyValues()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");}else {// 跳过这个空对象return;}}//用来判断是否需要继续依赖注入,false的时候就直接返回boolean continueWithPropertyPopulation = true;//hasInstantiationAwareBeanPostProcessors判断是否需要在注入属性值之前对这些参数值做最后一次的修改if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;//具体通过调用postProcessAfterInstantiation方法,如果调用返回false,标识不必继续进行依赖注入。if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {continueWithPropertyPopulation = false;break;}}}}//如果不需要依赖注入 这里就直接返回if (!continueWithPropertyPopulation) {return;}//初始化一个默认的属性值PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);//如果配置文件显示的配置了依赖注入,就不会走以下的逻辑。//如果设置了相关的依赖配置方式,会遍历bean中的所有属性,根据类型和名称来完成相应注入,无需额外配置if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {//对现有的属性值进行深度拷贝MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// 根据名称注入if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// 根据类型注入if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}//重新赋值属性值pvs = newPvs;}//这里检测了是否配置了后处理器。boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();//判断是否需要进行依赖检测boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);PropertyDescriptor[] filteredPds = null;//配置了后处理器if (hasInstAwareBpps) {//如果没有属性值,就从配置文件中获取。if (pvs == null) {pvs = mbd.getPropertyValues();}//逐一的对每一个后处理器,进行处理for (BeanPostProcessor bp : getBeanPostProcessors()) {//判断类型,校验是否是实例前后使用的处理器(后处理器分为实例化(BeanPostProcessor)、初始化(InstantiationAwareBeanPostProcessor)的两种)if (bp instanceof InstantiationAwareBeanPostProcessor) {//类型强制转换InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;//进行后处理PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {//筛选出所有需要进行依赖检测的属性编辑器filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}//对所有需要依赖检测的属性进行后处理pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}//再次更新属性pvs = pvsToUse;}}}if (needsDepCheck) {if (filteredPds == null) {//筛选出所有需要进行依赖检测的属性编辑器filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}//依赖检测checkDependencies(beanName, mbd, filteredPds, pvs);}if (pvs != null) {//将属性注入到bean中applyPropertyValues(beanName, mbd, bw, pvs);}
}
在populateBean函数中提供了属性注入的逻辑框架。
1.InstantiationAwareBeanPostProcessor处理器的PostProcessAfterInstantiation函数的应用。次函数可以控制程序是否继续进行属性填充。
2.根据注入类型(根据属性名或者根据属性类型),提起依赖的Bean,统一存入PropertyValues中。
3.应用InstantiationAwareBeanPostProcessor处理器的postProcessPropertyValues方法,对属性获取完毕填充前对属性的再次处理。
4.将所有PropertyValues中的属性填充到bean中。
上面最重要的3个方法分别是autowireByName、autowireByType和applyPropertyValues,接下来进一步逐一分析这几个功能的实现细节。
一、autowireByName
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {//寻找bw中需要依赖注入的属性。String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);for (String propertyName : propertyNames) {if (containsBean(propertyName)) {//递归初始化相关的BeanObject bean = getBean(propertyName);//存放依赖注入的属性值pvs.add(propertyName, bean);//进行注册依赖registerDependentBean(propertyName, beanName);if (logger.isTraceEnabled()) {logger.trace("Added autowiring by name from bean name '" + beanName +"' via property '" + propertyName + "' to bean named '" + propertyName + "'");}}else {if (logger.isTraceEnabled()) {logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +"' by name: no matching bean found");}}}
}
理解这个方法的功能并不太困难,无非是在传入的参数bw中找出已经加载的bean,并递归实例化,进而加入到pvs中。
二、autowireByType
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {//获取类型转换器(用户自定义的)TypeConverter converter = getCustomTypeConverter();if (converter == null) {//用户没有,我们就用spring自己的converter = bw;}//用于存放解析出来需要存放需要注入的属性Set<String> autowiredBeanNames = new LinkedHashSet<>(4);//寻找bw中需要依赖注入的属性。String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);for (String propertyName : propertyNames) {try {//获取对应属性名的属性描述器PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);//所有object类型的属性都不进行注入if (Object.class != pd.getPropertyType()) {//搜索指定属性的set方法MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);// 检测属性的类型能否成功转成目标类型boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());//创建需要被依赖注入的描述对象DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);//根据容器的Bean定义解析出依赖关系,返回需要被注入的bean对象Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);if (autowiredArgument != null) {//将属性和要进行注入的bean对象进行关联,保存到PropertyValues中pvs.add(propertyName, autowiredArgument);}for (String autowiredBeanName : autowiredBeanNames) {//进行注册依赖registerDependentBean(autowiredBeanName, beanName);if (logger.isTraceEnabled()) {logger.trace("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);}}
}
对于根据类型自动注入的实现来说,寻找bw中需要依赖注入的属性也是第一步,让后遍历这些属性寻找类型匹配的bean,其中最为复杂的就是寻找出对应类型的bean,最为重要的也是这个功能,实现的逻辑被封装在DefaultListableBeanFactory类中的resolveDependency方法中。
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());//对java8中的Optional类型进行处理if (Optional.class == descriptor.getDependencyType()) {return createOptionalDependency(descriptor, requestingBeanName);}//之前说过spring会提前曝光ObjectFactory,对此进行特殊处理else if (ObjectFactory.class == descriptor.getDependencyType() ||ObjectProvider.class == descriptor.getDependencyType()) {return new DependencyObjectProvider(descriptor, requestingBeanName);}//javax.inject.Provider也需要进行特殊处理else if (javaxInjectProviderClass == descriptor.getDependencyType()) {return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);}else {//对懒加载(@Lazy)进行处理,spring就不会立即创建注入属性,而是生成代理对象,来替代实例Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);if (result == null) {//通用的处理逻辑result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);}return result;}
}
接着上面的通用处理逻辑
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);try {//spring在第一次创建依赖的bean时,会保存这个bean的beanName作为shortcut//在第二次创建时,就可以直接根据beanName调用getBean方法,不需要在根据类型来重新查询一遍。Object shortcut = descriptor.resolveShortcut(this);if (shortcut != null) {return shortcut;}//注入属性的类型Class<?> type = descriptor.getDependencyType();//获取@Value中的value属性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());try {//尝试类型转换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()));}}//对数组、集合、容器类型进行处理。//确定集合类型->调用findAutowireCandidates方法,获取与组件类型匹配的map->符合beanNames就添加到autowiredBeanNames中。Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);if (multipleBeans != null) {return multipleBeans;}//非集合类型的处理,直接通过findAutowireCandidates获取到对应类型的beanMap<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);if (matchingBeans.isEmpty()) {if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}return null;}String autowiredBeanName;Object instanceCandidate;//如果类型匹配的bean不止一个,spring进行筛选,失败就抛出异常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 {// 只有一个bean与其匹配,直接使用这个beanMap.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();autowiredBeanName = entry.getKey();instanceCandidate = entry.getValue();}if (autowiredBeanNames != null) {autowiredBeanNames.add(autowiredBeanName);}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);}
}
这个段逻辑虽然长,但是逻辑还是十分清晰,首先尝试对解析器进行解析,如果没有解析成功,那么可能是使用默认的解析器没有做任何处理,或者是使用了自定义的解析器,但是对于集合这类的类型并不在解析器的范围里,所以还需要再次对不同的类型进行不同情况的处理。
三、applyPropertyValues
到了这里离成功就差最后一步,之前已经将所有需要依赖注入的属性和其对应注入的参数值存放到了PropertyValues中,但是还没有被应用到已经实例化的bean中。
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {//为空就是不需要注入if (pvs.isEmpty()) {return;}if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());}MutablePropertyValues mpvs = null;List<PropertyValue> original;if (pvs instanceof MutablePropertyValues) {mpvs = (MutablePropertyValues) pvs;if (mpvs.isConverted()) {try {//若该mpvs中的所有属性值都已经转换为对应的类型,则吧mpvs设置到beanWrapper中,bw.setPropertyValues(mpvs);return;}catch (BeansException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);}}original = mpvs.getPropertyValueList();}else {original = Arrays.asList(pvs.getPropertyValues());}//获取用户的自定义类型转换器TypeConverter converter = getCustomTypeConverter();if (converter == null) {converter = bw;}//获取BeanDefinitionValueResolver,用于bean定义对象中包含的值解析为应用于目标bean实例的实际值BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);// 用于存放实际解析后的属性List<PropertyValue> deepCopy = new ArrayList<>(original.size());boolean resolveNecessary = false;//遍历所有未解析的属性for (PropertyValue pv : original) {if (pv.isConverted()) {//已经解析过的直接添加deepCopy.add(pv);}else {//没有解析过的属性//获取属性名称String propertyName = pv.getName();//属性未经类型转换的值Object originalValue = pv.getValue();//解析后的值Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);Object convertedValue = resolvedValue;//这个属性可以写并且不是一个嵌套在其他属性中的属性,也不是集合的索引属性。boolean convertible = bw.isWritableProperty(propertyName) &&!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);if (convertible) {//用类型转换器进行转换convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);}//将转换后的值存储起来,避免对每一个需要创建的bean都再次转换if (resolvedValue == originalValue) {if (convertible) {pv.setConvertedValue(convertedValue);}deepCopy.add(pv);}else if (convertible && originalValue instanceof TypedStringValue &&!((TypedStringValue) originalValue).isDynamic() &&!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {pv.setConvertedValue(convertedValue);deepCopy.add(pv);}else {resolveNecessary = true;deepCopy.add(new PropertyValue(pv, convertedValue));}}}if (mpvs != null && !resolveNecessary) {//将mpvs标记成已经转换mpvs.setConverted();}// Set our (possibly massaged) deep copy.try {//构造MutablePropertyValues缓存到beanWrapper中bw.setPropertyValues(new MutablePropertyValues(deepCopy));}catch (BeansException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);}
}