阅读之前要注意的东西:本文就是主打流水账式的源码阅读,主导的是一个参考,主要内容需要看官自己去源码中验证。全系列文章基于 spring 源码 5.x 版本。
写在开始前的话:
阅读spring 源码实在是一件庞大的工作,不说全部内容,单就最基本核心部分包含的东西就需要很长时间去消化了:
实际上我在博客里贴出来的还只是一部分内容,更多的内容,我放在了个人,fork自 spring 官方源码仓了; 而且对源码的学习,必须是要跟着实际代码层层递进的,不然只是干巴巴的文字味同嚼蜡。
这个仓设置的公共仓,可以直接拉取。
在getBean 的调用链路中,如果是从零开始创建一个bean, 按照潦草的说法大致如下:
1.根据 beanName 从 beanFactory 读取 BeanDefinition
2.对BeanDefinition 进行简单的加工、转化 -> RootBeanDefinition
2.根据bean元数据(BeanDefinition) 中记录的信息,递归的去加载该bean 依赖的其它bean
3.根据bean 的作用域: [prototype、singleton...等等] 决定具体的创建bean的行为。
4.bean的实例化: (所谓实例化,可以理解为,从java 堆上创建了一个'全新'的对象。)
根据 BeanDefinition 获取: bean的类型、参数、自定义构造函数、 注入方式(直接注入: 无参构造函数,间接注入: FactoryBean、factory-bean + factory-method)。
最终根据上述的信息的配置情况,实例化一个bean。
5.上一步也提到,它只完成了实例化,但是如果有属性需要填充呢? 参考如下的例子:
<beans>
<bean id="myBean" class="demo.self.MySimpleBean">
<!-- property 是常量 -->
<property name="name" value="Bokerr"/>
<property name="age" value="27"/>
</bean>
<bean id="myBean" class="demo.self.MyBean">
<!-- property 是一个bean -->
<property name="bean1"><ref bean="populate1"/></property>
</bean>
<bean id="populate1" class="demo.self.populateBean"/>
</beans>
复制
为什么说填充的就是 property 属性呢? 【详见后文,populateBean方法的第一个判断。】
bean 创建实例化之后,还处于一个 '空白' 状态,所以需要经过填充操作,将配置的 property 属性的值注入。
这就引入了本文需要讲述的操作:populateBean
这里有个很重要、很重要、很重要的起手式:
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
你需要记住: PropertyValues(它是 bean的全部 property 解析后得到的元数据信息)
它是来自于 mbd 的。(也就是 BeanDefinition),它的对象声明周期受到 BeanFactory 管理;
下文中任意对 PropertyValues 及其属性的 set 操作,都可等效认为,实在对 BeanDefinition 作缓存操作。
/** * Populate the bean instance in the given BeanWrapper with the property values * from the bean definition. * * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param bw the BeanWrapper with bean instance */ protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { if (mbd.hasPropertyValues()) { // bean 有属性需要被填充,但是对象包装器 bw 为空 throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // 包装器为空,且不需要 填充任何属性 // Skip property population phase for null instance. return; } } // 给 InstantiationAwareBeanPostProcessors 最后一次机会,通过属性注入改变 bean. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 所有 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()的返回值将决定 // [是/否] 继续进行property属性填充 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } // 所有需要注入的属性, 对应的bean缓存 【这里明确从 BeanDefinition 上获取的 property 的定义】 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { // {重要操作1-根据Bean名称注入} [下文将展开详说] autowireByName(beanName, mbd, bw, newPvs); // 提取依赖的bean 保存到 pvs } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { // {重要操作1-根据Bean类型注入 <Class>} [下文将展开详说] autowireByType(beanName, mbd, bw, newPvs); // 提取依赖的bean 缓存到 pvs } pvs = newPvs; } // beanFactory 是否已经注册了: bean 实例化相关的 "后置处理器" boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); // 是否需要依赖检查 boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { if (pvs == null) { pvs = mbd.getPropertyValues(); } // 过滤属性描述符,为依赖检查做准备 PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) {// 后处理器 ?? for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 主要这里是相同的后置处理器,不同的方法 // 字段填充的前置检查 pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) {// 依赖检查, depend-on 属性,spring-3.0弃用 checkDependencies(beanName, mbd, filteredPds, pvs); } } if (pvs != null) { // 属性填充 {重要操作2} [下文将展开详说] applyPropertyValues(beanName, mbd, bw, pvs); // 将 propertyValue 应用/注入 到 bean 中 } }
复制
这里重点说两个操作:
autowireByName(beanName, mbd, bw, newPvs);
autowireByType(beanName, mbd, bw, newPvs);
applyPropertyValues(beanName, mbd, bw, pvs);
/** * Fill in any missing property values with references to * other beans in this factory if autowire is set to "byName". * * @param beanName the name of the bean we're wiring up. * Useful for debugging messages; not used functionally. * @param mbd bean definition to update through autowiring * @param bw the BeanWrapper from which we can obtain information about the bean * @param pvs the PropertyValues to register wired objects with */ protected void autowireByName( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { // 从 BeanDefinition 读取,非-常量注入的属性,这里返回的都是 property 指向别的 bean的场景 // 这里会忽略: 基本类型、字符串常量等等 property String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { if (containsBean(propertyName)) { // 递归加载依赖的bean Object bean = getBean(propertyName); pvs.add(propertyName, bean); // 在容器中记录 bean 及其依赖的 bean之间的关系, 不妨进去瞅瞅 registerDependentBean(propertyName, beanName); if (logger.isDebugEnabled()) { logger.debug("Added autowiring by name from bean name '" + beanName + "' via property '" + propertyName + "' to bean named '" + propertyName + "'"); } } else { // 根据beanName 未定位到bean, 记录到日志。[说明该 property 所依赖的可能并不是一个 bean,可能只是一个普通的常量。] if (logger.isTraceEnabled()) { logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName + "' by name: no matching bean found"); } } } }
复制
上文的内容很简单:
/** * Return an array of non-simple bean properties that are unsatisfied. * These are probably unsatisfied references to other beans in the * factory. Does not include simple properties like primitives or Strings. * * @param mbd the merged bean definition the bean was created with * @param bw the BeanWrapper the bean was created with * @return an array of bean property names * @see org.springframework.beans.BeanUtils#isSimpleProperty */ protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) { Set<String> result = new TreeSet<>(); PropertyValues pvs = mbd.getPropertyValues(); PropertyDescriptor[] pds = bw.getPropertyDescriptors(); for (PropertyDescriptor pd : pds) { // 有 setter方法 // && 没有别识别过的依赖 // && 已经解析过的property字段中不包含该字段 // && property的类型不是简单类型(Date、Number、CharSequence、Enum等等) if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) && !BeanUtils.isSimpleProperty(pd.getPropertyType())) { result.add(pd.getName()); } } return StringUtils.toStringArray(result); }
复制
/** * Abstract method defining "autowire by type" (bean properties by type) behavior. * <p>This is like PicoContainer default, in which there must be exactly one bean * of the property type in the bean factory. This makes bean factories simple to * configure for small namespaces, but doesn't work as well as standard Spring * behavior for bigger applications. * * @param beanName the name of the bean to autowire by type * @param mbd the merged bean definition to update through autowiring * @param bw the BeanWrapper from which we can obtain information about the bean * @param pvs the PropertyValues to register wired objects with */ protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { TypeConverter converter = getCustomTypeConverter(); // 获取自定义类型转换器 if (converter == null) { converter = bw; } Set<String> autowiredBeanNames = new LinkedHashSet<>(4); // 缓存依赖关系映射 // 从 BeanDefinition 读取,非-常量注入的属性,这里返回的都是 property 指向别的 bean的场景 // 这里会忽略: 基本类型、字符串常量等等 property String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { try { // 我们这是根据 bean Type 注入,所以这里浅浅的获取了一下, bean的类对象反射信息 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); // 探测属性指定的set 方法 // Do not allow eager init for type matching in case of a prioritized post-processor. boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered); // 依赖描述符 DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); // 解析指定 beanName 的属性所匹配的值, // 并把解析到的属性名称存储在 autowiredBeanNames 中 // 当存在多个属性被封装到一起时: // @Autowired List<A> aList; 会把 所有 A 类型的bean 都注入其中 autowiredBeans (复数个) Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter); // 寻找类型匹配的 bean 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); } } }
复制
这里是根据 property 的类型来注入的,比起根据 propertyName 注入, 这里的操作复杂得多
如果想要深究 resolveDependency() 方法,可以下载我个人fork 的spring源码仓; 我在源码里也加了详细注释。
书接上回 现在我们看第二个重点操作:
/** * Apply the given property values, resolving any runtime references * to other beans in this bean factory. Must use deep copy, so we * don't permanently modify this property. * * @param beanName the bean name passed for better exception information * @param mbd the merged bean definition * @param bw the BeanWrapper wrapping the target object * @param pvs the new property values */ 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) { // 实际上,如果执行过: autowireByType 和 autowireByName 后注入的 <property, propertyValue> mpvs = (MutablePropertyValues) pvs; if (mpvs.isConverted()) { // 根据 name / type 解析到的 bean 已经被 转化为 具体类型 那么直接进行注入操作 // Shortcut: use the pre-converted values as-is. try { // 将解析完成的 <property,propertyValue> 逐个应用到包装器: BeanWrapper bw.setPropertyValues(mpvs); return; } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } } original = mpvs.getPropertyValueList(); } else { // 同样 applyPropertyValues 也可能在别的场景中被调用: // 该场景中,PropertyValues 尚未进行任意的 property 的注入操作 // 所以进入当前分支,继续往下分析。 original = Arrays.asList(pvs.getPropertyValues()); } // 获取自定义-转换器 其实这个应该并不陌生,在 populateBean().autowireByType() 方法中见过 // 其实到这里,可以简单做个推论了: 接下来的篇幅中,所作的事情,可能会跟 property 的注入操作类似 TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; // 默认使用 bean 包装器 } // Spring表达式语言(SpEL) 解析器 #{bean.xxx} ${xx.key} // 可由 ApplicationContext 注入 BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // Create a deep copy, resolving any references for values. List<PropertyValue> deepCopy = new ArrayList<>(original.size()); boolean resolveNecessary = false; for (PropertyValue pv : original) { // 遍历 property 属性,将需要转换的属性,转换为对应的类型 if (pv.isConverted()) { // 已经转化过,直接添加 [BeanDefinition 缓存应用 或者 前边的环节已经处理过] deepCopy.add(pv); } else { // 先转换 后添加 String propertyName = pv.getName(); // 原始值 Object originalValue = pv.getValue(); // 包含SpEL表达式的解析 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); Object convertedValue = resolvedValue; // property 是否可覆盖? // 根据包装器 bw 判断 property 字段可写 && 并且 property 不是(索引/嵌套类型的属性)。 // 自引入概念:property 应该是一个 "原子属性" boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); if (convertible) { // 可以写入,且是一个"原子属性", 那么就可以进行转化了 // 这里不太适合再钻进去了,除非spring源码出bug了,否则如下的逻辑是不太有可能接触到的, // 可以简单做个盖棺定论: 这里会把 resolvedValue 转化为 property 字段所期望的值类型: // String: 2023-07-10 -> Date: 2023-07-10 00:00:00.000 // String: false -> Boolean: false convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } // Possibly store converted value in merged bean definition, // in order to avoid re-conversion for every created bean instance. if (resolvedValue == originalValue) { // 转换后的值(对象) 等价 原始值 if (convertible) { // PropertyValue 是元数据 BeanDefinition 的一环,这里等价为缓存 // 避免重复的转换操作 pv.setConvertedValue(convertedValue); } deepCopy.add(pv); } else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue) originalValue).isDynamic() && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) { // 转化后的值不等于原始值 // && 支持转换 // && 原始值是String // && 原始值不是动态的(常量) // && 转换后的值,不是集合、不是数组 pv.setConvertedValue(convertedValue); // BeanDefinition 设置缓存 deepCopy.add(pv); } else { // 上述情形之外的情况, 可以看到,区别是,这里没有被当作缓存设回 BeanDefinition 中 resolveNecessary = true; deepCopy.add(new PropertyValue(pv, convertedValue)); } } } if (mpvs != null && !resolveNecessary) { // mpvs 同样是 BeanDefinition 所包含的信息,这里也可视作缓存设置 mpvs.setConverted(); } // Set our (possibly massaged) deep copy. try { // 将解析完成的 <property,propertyValue> 逐个应用到包装器: BeanWrapper bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } }
复制
重要信息都放在注释里了。