在之前使用Spring的时候,我们都是使用Xml的方式进行配置,虽然现在大部分项目都改为了使用注解方式,但是我们这里还是讲解一下之前的Xml的方式Spring是怎样进行依赖注入的。下一节,我们将讲解注解方式Spring是如何进行注入的。
首先还是使用前面定义的两个类,Home和User。
@Data
public class Home {
private User user;
}
@Data
public class User {
private String name;
private String age;
}
在使用Xml配置的时候,我们通常会进行如下配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- 定义一个类型为User,name为user的Bean,并注入name和age属性 -->
<bean id="user" class="com.demo.User">
<property name="name" value="jack"/>
<property name="age" value="18"/>
</bean>
<!-- home中注入user有两种方式,Spring不推荐使用第二种方式,虽然第二种方式更简洁 -->
<!-- 如果两种方式同时指定,以第一种方式为准 -->
<!-- 第一种,通过property指定user字段注入user Bean -->
<bean id="home" class="com.demo.Home">
<property name="user" ref="user"/>
</bean>
<!-- 第二种,通过autowire="byName"指定自动注入,此时Spring会自动根据名称注入user Bean -->
<bean id="home" class="com.demo.Home" autowire="byName">
</bean>
</beans>
在之前的文章Spring系列-Spring的Bean创建流程我们已经从整体上讲解了Bean的创建流程,在Bean创建的过程中,依赖注入是发生在doGetBean()中的populateBean()方法中,下面我们再次看下populateBean()方法。
populateBean()
// AbstractAutowireCapableBeanFactory.java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// ...忽略注入无关代码
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
// 这里是处理自动注入的代码,也就是如果我们在xml中配置了autowire="byName"或者autowire="byType",便会走下面的
// 自动注入代码,如果不配置,默认是autowire="NO", 也就是不自动注入
// 需要注意的是,这里并没有真正进行注入,只是把需要注入的信息都准备好了,真正的注入是在最后的applyPropertyValues()
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 通过名称自动注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 通过类型自动注入
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 如果有InstantiationAwareBeanPostProcessor后置处理器,通过后置处理器处理属性,我们可以定义这种后置处理器修改获取
// 添加注入属性,注解属性注入就是在后置处理器中处理的,这篇我们先不考虑这里
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()) {
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) {
// 应用属性值,也就是注入属性
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
autowireByName()
这个方法比较简单,因为bean名称不能重复,所以该方法实际上就是通过属性名同beanFactory中获取Bean对象,然后保存到pvs中,以便接下来的属性赋值。
// AbstractAutowireCapableBeanFactory.java
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 获取不满足的非简单属性,这是什么意思?
// 就是获取符合条件注入条件但是在pvs不存在注入属性值的非简单属性(也就是bean),下面我们会详解
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
// 如果该属性是一个Bean,直接通过getBean获取该属性要注入的bean实例,然后添加到pvs集合中
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
// 注册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");
}
}
}
}
unsatisfiedNonSimpleProperties()
获取符合条件注入条件但是在pvs不存在注入属性值的非简单属性。
// AbstractAutowireCapableBeanFactory.java
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set<String> result = new TreeSet<>();
// 已经存在的属性值信息
PropertyValues pvs = mbd.getPropertyValues();
// 该bean的所有属性描述信息对象
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
// 这一步就是找该bean所有属性描述对象中符合自动注入条件,但是在pvs中不存在属性,如果pvs中已经存在就不用在寻找了
for (PropertyDescriptor pd : pds) {
// 存在属性的set方法
if (pd.getWriteMethod() != null
// 不属于要排除的属性依赖
&& !isExcludedFromDependencyCheck(pd)
// pvs中不存在该属性
&& !pvs.contains(pd.getName())
// 该属性不是一个简单属性
&& !BeanUtils.isSimpleProperty(pd.getPropertyType())) {
result.add(pd.getName());
}
}
return StringUtils.toStringArray(result);
}
判断该依赖属性是否需要排除?如果需要排除返回true, 不需要排除返回false
// AbstractAutowireCapableBeanFactory.java
// 什么样的属性属于要排除的属性呢?
protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
// 1. 没有set方法的属性要排除
// 2. 是CGLIB生成的方法,需要排除
// 3. 是代理对象而且被代理对象中不存在该属性set方法需要被排除
return (AutowireUtils.isExcludedFromDependencyCheck(pd) ||
// 4. 如果该属性类型为忽略依赖类型的集合中,则排除。可以通过getBeanFactory().ignoreDependencyInterface()
// 设置需要排除的类型
this.ignoredDependencyTypes.contains(pd.getPropertyType()) ||
// 5. 如果该属性的set方法为忽略依赖接口中定义的方法,则排除
// 在创建该类以及执行prepareBeanFactory()的时候,已经将一系列的Aware接口设置为了忽略接口
// 引为这些接口定义的方法有一个共同的特点,就是以set开头,都是setXXX()的格式
AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
}
判断什么样的方法需要被排除。
// AutowireUtils.java
public static boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
Method wm = pd.getWriteMethod();
// set方法为空不排除
// 因为前面已经判断了WriteMethod != null, 所以这里肯定不为空,暂时不知道这里是适配哪里的逻辑
if (wm == null) {
return false;
}
// 如果该方法的声明类不是CGLIB代理的对象,则不需要排除
if (!wm.getDeclaringClass().getName().contains("$$")) {
return false;
}
// 如果是CGLIB代理类,则拿到superClass,即被代理类,看被代理上是否定义了该属性的set方法,如果定义了,也不排除
Class<?> superclass = wm.getDeclaringClass().getSuperclass();
return !ClassUtils.hasMethod(superclass, wm);
}
该属性的set方法是否为忽略依赖接口中定义的方法。
// AutowireUtils.java
public static boolean isSetterDefinedInInterface(PropertyDescriptor pd, Set<Class<?>> interfaces) {
Method setter = pd.getWriteMethod();
if (setter != null) {
Class<?> targetClass = setter.getDeclaringClass();
for (Class<?> ifc : interfaces) {
// 判断该属性的声明类是否是该接口类型,并且该set方法是否在接口中进行了声明
if (ifc.isAssignableFrom(targetClass) && ClassUtils.hasMethod(ifc, setter)) {
return true;
}
}
}
return false;
}
判断是否为简单属性。
// BeanUtils.java
public static boolean isSimpleProperty(Class<?> type) {
// 如果是数组,获取数组类型进行判断
return isSimpleValueType(type) || (type.isArray() && isSimpleValueType(type.getComponentType()));
}
public static boolean isSimpleValueType(Class<?> type) {
return (Void.class != type && void.class != type &&
// 判断是否是基本类型或包装类型
(ClassUtils.isPrimitiveOrWrapper(type) ||
Enum.class.isAssignableFrom(type) ||
CharSequence.class.isAssignableFrom(type) ||
Number.class.isAssignableFrom(type) ||
Date.class.isAssignableFrom(type) ||
Temporal.class.isAssignableFrom(type) ||
URI.class == type ||
URL.class == type ||
Locale.class == type ||
Class.class == type));
}
registerDependentBean()
// AbstractAutowireCapableBeanFactory.java
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = canonicalName(beanName);
// 保存该bean与依赖bean的依赖关系
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
// 保存依赖bean与该bean的依赖关系
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
autowireByType()
该方法比autowireByName()要复杂,因为根据类型注入的话,一个类型还可能会有很多Bean实例对象,此时要挑选出最合适的一个。
// AbstractAutowireCapableBeanFactory.java
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 获取类型转换器,用于类型转化
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
// 如果类型转换器为null,将beanWrapper设置为converter,因为BeanWrapper实现了类型转换器接口,也是一个类型转换器
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
// 同autowireByName()一样,先找到需要处理的自动注入的属性名
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);
// 在优先后处理器的情况下,不允许使用 Eager init 进行类型匹配
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 解析依赖,这里的逻辑比较复杂,而且包含了其它的解析逻辑,所以这块在下一篇文章注解配置里讲解
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
// 添加到pvs
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);
}
}
}
filterPropertyDescriptorsForDependencyCheck()
该方法其实过滤掉不需要处理的属性后,将过滤后的属性返回并缓存起来。
// AbstractAutowireCapableBeanFactory.java
protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw, boolean cache) {
PropertyDescriptor[] filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
if (filtered == null) {
filtered = filterPropertyDescriptorsForDependencyCheck(bw);
if (cache) {
PropertyDescriptor[] existing =
this.filteredPropertyDescriptorsCache.putIfAbsent(bw.getWrappedClass(), filtered);
if (existing != null) {
filtered = existing;
}
}
}
return filtered;
}
// 看一看到该方法中又用到了上面我们说的isExcludedFromDependencyCheck()方法
protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw) {
List<PropertyDescriptor> pds = new ArrayList<>(Arrays.asList(bw.getPropertyDescriptors()));
pds.removeIf(this::isExcludedFromDependencyCheck);
return pds.toArray(new PropertyDescriptor[0]);
}
checkDependencies()
检查依赖关系,其实就是判断需要注入依赖的属性是否都有了可以注入的值。
// AbstractAutowireCapableBeanFactory.java
protected void checkDependencies(
String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, @Nullable PropertyValues pvs)
throws UnsatisfiedDependencyException {
int dependencyCheck = mbd.getDependencyCheck();
for (PropertyDescriptor pd : pds) {
// 如果属性set方法存在,当时pvs中到现在还没有该属性的赋值信息,则进行校验
if (pd.getWriteMethod() != null && (pvs == null || !pvs.contains(pd.getName()))) {
boolean isSimple = BeanUtils.isSimpleProperty(pd.getPropertyType());
// 是否是校验所有,则直接报错
boolean unsatisfied = (dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_ALL) ||
// 如果该属性是简单属性,并且需要校验简单属性,则报错
(isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
// 如果该属性不是简单属性,并且需要校验非简单属性,则报错
(!isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
if (unsatisfied) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, pd.getName(),
"Set this property value or disable dependency checking for this bean.");
}
}
}
}
applyPropertyValues()
真正的为属性赋值。
// AbstractAutowireCapableBeanFactory.java
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;
// MutablePropertyValues 是 PropertyValues 的默认实现类,它允许简单的属性操作,并提供构造函数来支持从Map
// 进行深度复制和构造
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
// 如果需要注入的属性都已经进行了转换,则可以直接注入,说明在前面的步骤已经处理过了
try {
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;
}
// 在bean工厂实现中使用的Helper类,解析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();
// 这里是自动注入属性的标记对象,如果标记为这个对象,最后是通过AutowireCapableBeanFactory#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);
}
// 解析属性注入值,如果像我们开头所说的第一种配置方式,这里获取的originalValue为RuntimeBeanReference,
// 这代表运行时解析,这一步就会将RuntimeBeanReference解析为真正的bean对象
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
// 如果有set方法,并且不是内嵌属性就可以进行转换
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
// 对值进行转换,对于我们bean对象注入来说没什么太大作用,因为转换之后还是该Bean,但是对其它类型不一致的就有必要了
// 例如将字符串转换为Integer等,类型转换在后面会专门写文章讲解
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// 如果解析后的值和原始值一样,并且该值可转换,则设置转换后的值
// 这里是在某些情况下才会走,因为Spring很复杂,而且方法通用,所以代码需要兼容各种情况
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));
}
}
}
// 如果mpvs不为空,而且不需要解析,说明所有需要注入的属性都已经解析了,则设置mpvs为已转换,这里设置的目的是这里处理了
// 后面的步骤就不用再次处理了,否则后面还需要处理转换
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
try {
// 对属性进行赋值
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
resolveValueIfNecessary()
该方法就是根据值的不同类型进行不同的处理,实际上就是解析为真正的注入对象。因为在解析BeanDefinition的时候,不同的情况我们需要在pvs中设置不同的占位,这里就是根据签名不同的占位执行不同的解析。
// BeanDefinitionValueResolver.java
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
// 像我们上面的第一种配置ref="user",就是在BeanDefinition保存为RuntimeBeanReference,这里则会真正去拿到真正的Bean
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
}
else if (value instanceof RuntimeBeanNameReference) {
String refName = ((RuntimeBeanNameReference) value).getBeanName();
refName = String.valueOf(doEvaluate(refName));
if (!this.beanFactory.containsBean(refName)) {
throw new BeanDefinitionStoreException(
"Invalid bean name '" + refName + "' in bean reference for " + argName);
}
return refName;
}
else if (value instanceof BeanDefinitionHolder) {
// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
}
else if (value instanceof BeanDefinition) {
// Resolve plain BeanDefinition, without contained name: use dummy name.
BeanDefinition bd = (BeanDefinition) value;
String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
ObjectUtils.getIdentityHexString(bd);
return resolveInnerBean(argName, innerBeanName, bd);
}
else if (value instanceof DependencyDescriptor) {
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
Object result = this.beanFactory.resolveDependency(
(DependencyDescriptor) value, this.beanName, autowiredBeanNames, this.typeConverter);
for (String autowiredBeanName : autowiredBeanNames) {
if (this.beanFactory.containsBean(autowiredBeanName)) {
this.beanFactory.registerDependentBean(autowiredBeanName, this.beanName);
}
}
return result;
}
else if (value instanceof ManagedArray) {
// May need to resolve contained runtime references.
ManagedArray array = (ManagedArray) value;
Class<?> elementType = array.resolvedElementType;
if (elementType == null) {
String elementTypeName = array.getElementTypeName();
if (StringUtils.hasText(elementTypeName)) {
try {
elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
array.resolvedElementType = elementType;
}
catch (Throwable ex) {
// Improve the message by showing the context.
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error resolving array type for " + argName, ex);
}
}
else {
elementType = Object.class;
}
}
return resolveManagedArray(argName, (List<?>) value, elementType);
}
else if (value instanceof ManagedList) {
// May need to resolve contained runtime references.
return resolveManagedList(argName, (List<?>) value);
}
else if (value instanceof ManagedSet) {
// May need to resolve contained runtime references.
return resolveManagedSet(argName, (Set<?>) value);
}
else if (value instanceof ManagedMap) {
// May need to resolve contained runtime references.
return resolveManagedMap(argName, (Map<?, ?>) value);
}
else if (value instanceof ManagedProperties) {
Properties original = (Properties) value;
Properties copy = new Properties();
original.forEach((propKey, propValue) -> {
if (propKey instanceof TypedStringValue) {
propKey = evaluate((TypedStringValue) propKey);
}
if (propValue instanceof TypedStringValue) {
propValue = evaluate((TypedStringValue) propValue);
}
if (propKey == null || propValue == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error converting Properties key/value pair for " + argName + ": resolved to null");
}
copy.put(propKey, propValue);
});
return copy;
}
else if (value instanceof TypedStringValue) {
// Convert value to target type here.
TypedStringValue typedStringValue = (TypedStringValue) value;
Object valueObject = evaluate(typedStringValue);
try {
Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
if (resolvedTargetType != null) {
return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
}
else {
return valueObject;
}
}
catch (Throwable ex) {
// Improve the message by showing the context.
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error converting typed String value for " + argName, ex);
}
}
else if (value instanceof NullBean) {
return null;
}
else {
return evaluate(value);
}
}
convertForProperty()
这里就是将输入的注入值进行类型转换,转换为我们定义的注入类型。
private Object convertForProperty(
@Nullable Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {
// 转换最终都会调用到this.typeConverterDelegate.convertIfNecessary(),这个我们后面再说
if (converter instanceof BeanWrapperImpl) {
return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName);
}
else {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);
}
}
setPropertyValues()
// AbstractNestablePropertyAccessor.java
public void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException {
AbstractNestablePropertyAccessor nestedPa;
try {
// 获取内嵌属性访问器
// 什么是内嵌属性?例如:home.user.age, names[0], users["Jack"].age等等
nestedPa = getPropertyAccessorForPropertyPath(propertyName);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
"Nested property in path '" + propertyName + "' does not exist", ex);
}
/**
protected static class PropertyTokenHolder {
// 对应bean中的属性名称,如嵌套属性user['Jack'].age 在bean中的属性名称为user
public String actualName;
// 将原始的嵌套属性处理成标准的token,如user["Jack"].age处理成user[Jack].age
public String canonicalName;
// 这个数组存放的是嵌套属性[]中的内容,如user["Jack"].age处理成 ["Jack", "age"]
public String[] keys;
*/
// 获取属性token,其实就是将上面的内嵌属性转换为好解析的格式进行保存
PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
// 赋值
nestedPa.setPropertyValue(tokens, new PropertyValue(propertyName, value));
}
// AbstractNestablePropertyAccessor.java
protected AbstractNestablePropertyAccessor getPropertyAccessorForPropertyPath(String propertyPath) {
// 这里是获取内嵌属性第一个分隔符的位置,其实就是找第一个.或者[的位置
int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(propertyPath);
// 如果位置>-1,则说明是内嵌属性,递归处理内嵌属性,获取每一个内嵌属性访问器
// 每一个内嵌属性都需要有各自的属性访问器进行处理
if (pos > -1) {
String nestedProperty = propertyPath.substring(0, pos);
String nestedPath = propertyPath.substring(pos + 1);
// 获取属性访问器
AbstractNestablePropertyAccessor nestedPa = getNestedPropertyAccessor(nestedProperty);
// 将内嵌属性去除上一层后进行递归处理,例如:home.user.age去除home后再处理user.age
return nestedPa.getPropertyAccessorForPropertyPath(nestedPath);
}
else {
return this;
}
}
// AbstractNestablePropertyAccessor.java
protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
if (tokens.keys != null) {
// 处理内嵌属性
processKeyedProperty(tokens, pv);
}
else {
// 处理普通属性
processLocalProperty(tokens, pv);
}
}
// AbstractNestablePropertyAccessor.java
private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
// 获取属性处理器进行属性注入
PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
Object oldValue = null;
try {
Object originalValue = pv.getValue();
Object valueToApply = originalValue;
if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
if (pv.isConverted()) {
// 如果属性值已经转换过,直接获取转换过的属性值
valueToApply = pv.getConvertedValue();
}
else {
if (isExtractOldValueForEditor() && ph.isReadable()) {
try {
// 如果没有转换过,获取原始属性值
oldValue = ph.getValue();
}
catch (Exception ex) {
if (ex instanceof PrivilegedActionException) {
ex = ((PrivilegedActionException) ex).getException();
}
if (logger.isDebugEnabled()) {
logger.debug("Could not read previous value of property '" +
this.nestedPath + tokens.canonicalName + "'", ex);
}
}
}
// 进行转换
valueToApply = convertForProperty(
tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor());
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
// 注入
ph.setValue(valueToApply);
}
catch (TypeMismatchException ex) {
throw ex;
}
setValue
// BeanPropertyHandler.java
public void setValue(@Nullable Object value) throws Exception {
Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
this.pd.getWriteMethod());
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(writeMethod);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
() -> writeMethod.invoke(getWrappedInstance(), value), acc);
}
catch (PrivilegedActionException ex) {
throw ex.getException();
}
}
else {
// 通过反射,调用set方法进行赋值
ReflectionUtils.makeAccessible(writeMethod);
writeMethod.invoke(getWrappedInstance(), value);
}
}
至此,我们就说完了Xml配置的属性依赖注入的逻辑,但是里面还有很多的细节我们还没有说到,具体细节后面会慢慢讲到。