方志朋 2020-02-20
目录
本章主要分析 Spring IoC 依赖注入的源码,首先分析最基本的手动注入,再分析两种自动注入方式 - 名称注入和类型注入,这两种注入最核心的是如何查找依赖,Spring 中专门提供了 resolveDependency API 用于根据类型查找依赖,最后我们再回过头再看一下构造器注入和工厂方法注入。
首先,我们要了解一下 Spring Bean 的整个创建过程,doCreateBean 方法主要完成了以下几件事:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // 1. 实例化Bean,构造器注入或工厂方法注入 BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args); // 2. 后置处理器修改Bean的定义BeanDefinition:bdp#postProcessMergedBeanDefinition applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); // 3. 提前将Bean暴露到IoC容器中,用于解决循环依赖 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // 4. populateBean属性注入的核心方法,initializeBean则执行bean初始化方法 Object exposedObject = bean; populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); // 5. 注册bean的依赖关系,用于bean销毁用 registerDisposableBeanIfNecessary(beanName, bean, mbd); return exposedObject; }
说明: 在 Bean 的创建过程中有两个方法都可以进行依赖注入。
createBeanInstance
:方法实例化时,构造器注入或工厂方法注入。populateBean
:"Setter 注入" 或 "Field 注入" 或 "方法注入" 等。下面,我们看一下 populateBean 方法是怎么进行属性注入的。populateBean 处理了 Spring 的各种依赖注入:包括自动注入(名称注入和类型注入)、注解注入(@Autowired 和 @Value 等)、手动注入等。
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // 1. 判断是否需要进行属性注入:ibp#postProcessAfterInstantiation if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 2. 自动注入:包括名称注入和类型注入 int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 2.1 自动根据名称注入 if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 2.2 自动根据类型注入 if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); // 3. 注解注入:后置处理器ibp#postProcessProperties,大名鼎鼎的@Autowired就是在这处理的。 PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { 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; } } } // 4. 依赖检查,循环依赖... if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } // 5. 手动依赖注入 if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
说明: 代码很长,但逻辑非常清晰,populateBean 方法依次处理自动注入,注解注入,手动注入。每种注入方式的代码基本上都是独立的,我们先越过自动注入和注解注入,先深入分析手动注入 applyPropertyValues 方法。
本小节指的手动注入是指手动指定注入字段名称,解析后添加到 bd.propertyValues 中。如
<bean id="beanA" class="com.binarylei.spring.ioc.injection.BeanA"> <property name="beanB" ref="beanB"/> </bean>
在分析 applyPropertyValues 源码之前,我们先认知一下这几个类:
applyPropertyValues 方法的主要逻辑是遍历 bd.propertyValues 中的 PropertyValue 属性,根据引用类型提取出对象实例,再将这个对象实例转换成可以直接注入的实例。
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { MutablePropertyValues mpvs = null; List<PropertyValue> original; // 1. 获取List<PropertyValue>,如果已经解析过,则直接注入后返回 if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; // MutablePropertyValues已经解析,直接注入,在方法解析后会缓存已经解析的PropertyValue if (mpvs.isConverted()) { // bean注入 bw.setPropertyValues(mpvs); return; } original = mpvs.getPropertyValueList(); } else { original = Arrays.asList(pvs.getPropertyValues()); } // 2. TypeConverter:用于类型转换。 // BeanDefinitionValueResolver:用于解析PropertyValue,如间接引用替换成直接对象 TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // 3. 逐个解析PropertyValue List<PropertyValue> deepCopy = new ArrayList<>(original.size()); boolean resolveNecessary = false; for (PropertyValue pv : original) { if (pv.isConverted()) { // 3.1 PropertyValue已经解析 deepCopy.add(pv); } else { String propertyName = pv.getName(); Object originalValue = pv.getValue(); // 3.2 标记位,实际使用resolveDependency方法查找依赖注入的对象 if (originalValue == AutowiredPropertyMarker.INSTANCE) { Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod(); if (writeMethod == null) { throw new IllegalArgumentException("Autowire marker for property without write method: " + pv); } originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true); } // 3.3 提取真实的对象 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); // 3.4 类型转换 Object convertedValue = resolvedValue; boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); if (convertible) { convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } // 3.5 缓存解析后的PropertyValue:resolvedValue -> convertedValue // 3.5.1 缓存:实例没有发生变化,比如只进行属性注入等 if (resolvedValue == originalValue) { if (convertible) { pv.setConvertedValue(convertedValue); } deepCopy.add(pv); // 3.5.2 缓存:TypedStringValue将String转换成指定类型targetType) // TypedStringValue不需要动态转换,且不是集合或数据 } else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue) originalValue).isDynamic() && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) { pv.setConvertedValue(convertedValue); deepCopy.add(pv); // 3.5.3 不缓存:每次都重新解析 } else { resolveNecessary = true; deepCopy.add(new PropertyValue(pv, convertedValue)); } } } // 4. 所有的字段都能成功解析,才会标记为转换完成,否则下次还需要动态解析 if (mpvs != null && !resolveNecessary) { mpvs.setConverted(); } // 5. bean依赖注入 bw.setPropertyValues(new MutablePropertyValues(deepCopy)); }
说明: 这段代码如上所述,完成了解析对象、类型转换、结果缓存、最后进行属性注入,但这些核心功能基本上都委托给对应的类完成。applyPropertyValues 本身却很简单:
解析对象:委托 BeanDefinitionValueResolver 完成。
类型转换:委托 TypeConverter 完成。
属性注入:委托 bw 完成。
结果缓存:applyPropertyValues 方法本身完成的最大功能。我们就看一下什么情况会使用缓存?
注入的字段 propertyName 必须有写方法(setter method)且注入的该字段不存在嵌套的情况(eg: person.user.name)
boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
解析后的对象实例没有被替换(地址匹配):如动态代理等,会直接替换对象。
resolvedValue == originalValue
对象类型是 TypedStringValue,不需要动态转换,且不是集合或数据
convertible && originalValue instanceof TypedStringValue && !((TypedStringValue) originalValue).isDynamic() && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))
BeanDefinitionValueResolver#resolveValueIfNecessary(argName, value) 方法功能:解析 value 的真实类型,value 的类型不同,处理的结果也不同。本质就是进行依赖查找。
如 applyPropertyValues 中的 AutowiredPropertyMarker.INSTANCE 类型:表示使用 beanFactory#resolveDependency 进行依赖查找。BeanDefinitionBuilder 添加属性时就会使用时这些类型。
public BeanDefinitionBuilder addPropertyValue(String name, @Nullable Object value) { this.beanDefinition.getPropertyValues().add(name, value); return this; } public BeanDefinitionBuilder addPropertyReference(String name, String beanName) { this.beanDefinition.getPropertyValues().add(name, new RuntimeBeanReference(beanName)); return this; } public BeanDefinitionBuilder addAutowiredProperty(String name) { this.beanDefinition.getPropertyValues().add(name, AutowiredPropertyMarker.INSTANCE); return this; }
依赖注入过程中,populateBean 调用 applyPropertyValues 方法进行属性注入之前,还有一步是依赖检查,默认是关闭的。在 AbstractBeanDefinition 中定义了如下 4 种检查方案,默认为 DEPENDENCY_CHECK_NONE。
public static final int DEPENDENCY_CHECK_NONE = 0; public static final int DEPENDENCY_CHECK_OBJECTS = 1; public static final int DEPENDENCY_CHECK_SIMPLE = 2; public static final int DEPENDENCY_CHECK_ALL = 3;
依赖检查 checkDependencies 方法,检查的 Bean 中 setter 方法对应的字段是否都是 value 值注入,如果字段没有 setter 则不用检查,又分为简单类型和对象类型检查。
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); }
说明: populateBean 先调用 filterPropertyDescriptorsForDependencyCheck 过滤出需要进行依赖检查的字段,默认只要字段有 setter 方法,除开基本类型或特殊的类型,都要进行校验。checkDependencies 则判断 pvs 中是否包含 pd.getName(),如果不包含则根据检查级别抛出异常。
依赖检查因为默认是关闭的,而且代码也很简单,就不多说了。而且开发中好像也没有使用过这个功能。
Spring 提供了三种自动注入的手段:名称注入、类型注入、构造器注入。其中构造器注入本质是类型注入。
无论是名称注入还是类型注入,都是通过依赖查找,通过 pvs.add(propertyName, propertyValue) 将属性添加到 bd.pvs 中,然后统一调用 bw.setPropertyValues(pvs) 将属性注入到 bean 中。
unsatisfiedNonSimpleProperties 方法定义了 bean 中那些字段需要自动注入。正常情况下,只要定义了 setter 方法的字段都会自动注入。
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) { Set<String> result = new TreeSet<>(); PropertyValues pvs = mbd.getPropertyValues(); PropertyDescriptor[] pds = bw.getPropertyDescriptors(); for (PropertyDescriptor pd : pds) { if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) && !BeanUtils.isSimpleProperty(pd.getPropertyType())) { result.add(pd.getName()); } } return StringUtils.toStringArray(result); }
下面看一下那些方法不需要进行依赖检查。
protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) { return (AutowireUtils.isExcludedFromDependencyCheck(pd) || this.ignoredDependencyTypes.contains(pd.getPropertyType()) || AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces)); }
说明: 有三种情况:一是写方法不存在;二是字段类型为指定不需要检查的类型 ignoredDependencyTypes;三是在指定接口中的方法也不需要进行类型检查 ignoredDependencyInterfaces。Spring 没有默认的 ignoredDependencyTypes 类型,但指定默认的接口 ignoredDependencyInterfaces 如下,这些 Aware 接口都是通过接口回调进行注入:
// AbstractAutowireCapableBeanFactory ignoreDependencyInterface(BeanNameAware.class); ignoreDependencyInterface(BeanFactoryAware.class); ignoreDependencyInterface(BeanClassLoaderAware.class); // AbstractApplicationContext#prepareBeanFactory beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
当注入模式为 AUTOWIRE_BY_NAME,采用依赖注入,目前只支持 XML 配置。
<bean id="beanA" class="com.binarylei.spring.ioc.injection.BeanA" autowire="byName"/>
autowireByName 的代码也很简单。
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { if (containsBean(propertyName)) { Object bean = getBean(propertyName); pvs.add(propertyName, bean); registerDependentBean(propertyName, beanName); } } }
说明: 根据 getBean(propertyName) 查找依赖。
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); String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName); if (Object.class != pd.getPropertyType()) { MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd); // eager 类型 @Lazy 属性,是否提前初始化 boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered); // DependencyDescriptor 封装了字段注入的详细信息 DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); // (核心)依赖查找最核心的API Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter); if (autowiredArgument != null) { pvs.add(propertyName, autowiredArgument); } // 注册依赖关系,用于 bean 销毁 for (String autowiredBeanName : autowiredBeanNames) { registerDependentBean(autowiredBeanName, beanName); } autowiredBeanNames.clear(); } } }
说明: 调用 beanFactory#resolveDependency 方法查找依赖。重点还要说明一点的是
每天用心记录一点点。内容也许不重要,但习惯很重要!