双十一过去了,终于可以把这篇博客补上了。
本文将分析BeanWrapperImpl,出现了大量的源码。如果你对BeanWrapper有相当的了解,请略过;如果想稍微了解一下BeanWrapper,可能需要关注一下源码。
--------------------------------------------
学习 Spring 核心是一件比较耗费精力的过程,代码太多,代码的层次也比较深。每次我都是在上午看代码,把一天中精力比较集中的时间段留给了他。在【Spring IOC -依赖注入(概述 getBean)】一文中,我们了解了 Spring 依赖注入的大概过程。本次我们要着重说明一下依赖注入中的 Bean 实例化,以及自动注入的实现方式。
1. 本次分享需要解决的几个问题
- 不得不说的 BeanWrapper
- 实例化的经过的各层传递
- 常用的自动注入如何实现
2. 不得不说的 BeanWrapper
BeanWrapper 是 Spring 框架中十分重要的技术支持组件。他的实现类大概有1千多行代码,很长,但是功能也是比较内聚的。BeanWrapper 的主要作用是把所有的 Bean 的属性都可以集中处理。这种集中处理的机制来自于 Java 的反射。通过 Java 的反射,可以把 Bean 的属性抽取出来,然后在通过反射的方式进行赋值。这种方式使 Spring 可以用同一种方式来处理 Bean 的属性。
2.1 BeanWrapper 的实现类图
上图中可以发现默认实现 BeanWrapper 的实现类 BeanWrapperImpl 通过继承 AbstractPropertyAccessor 来增强其属性的赋值功能。这个过程中你可以定义自己的类型处理器。在org.springframework.beans.propertyeditors包下面是 Spring 扩展自己定义的类型处理器,如果需要可以扩展自己处理器注册到容器中。这些不是这次讨论的主题,就不详细说明了。
2.2 构建 BeanWrapper 的实例
构建一个 BeanWrapper 实例有很多种方式,可以指定需要实例化的 Bean.class,可以指定需要包装的 Bean 实例等。下面就 BeanWrapper 的属性的进行说明。
Object object; |
被包装的Bean实例,如果传递了对应的 class,通过 BeanUtils 实例化一个 |
String nestedPath = ""; |
嵌套路径。例如如果BeanA里面包含属性BeanB,那么访问BeanA的BeanB属性的路径是“beanA.beanB”。那BeanB的嵌套路径就是“beanA.” |
Object rootObject; |
嵌套上级Bean实例,如果没有上级,就是自己本身 |
TypeConverterDelegate typeConverterDelegate; |
类型转换器代理实现 |
CachedIntrospectionResults cachedIntrospectionResults; |
缓存Bean实例对应的class、属性等信息(beanInfo),在使用的Bean的信息,可以从中获取。(Java 内省机制) |
Map<String, BeanWrapperImpl> nestedBeanWrappers; |
保存嵌套路径到BeanWrapper实例的映射关系保存。 |
构造方法重要的有两个:
/** * Create new BeanWrapperImpl for the given object, * registering a nested path that the object is in. * @param object object wrapped by this BeanWrapper * @param nestedPath the nested path of the object * @param rootObject the root object at the top of the path */ public BeanWrapperImpl(Object object, String nestedPath, Object rootObject) { registerDefaultEditors(); setWrappedInstance(object, nestedPath, rootObject); } /** * Create new BeanWrapperImpl for the given object, * registering a nested path that the object is in. * @param object object wrapped by this BeanWrapper * @param nestedPath the nested path of the object * @param superBw the containing BeanWrapper (must not be <code>null</code>) */ private BeanWrapperImpl(Object object, String nestedPath, BeanWrapperImpl superBw) { setWrappedInstance(object, nestedPath, superBw.getWrappedInstance()); setExtractOldValueForEditor(superBw.isExtractOldValueForEditor()); setAutoGrowNestedPaths(superBw.isAutoGrowNestedPaths()); setAutoGrowCollectionLimit(superBw.getAutoGrowCollectionLimit()); setConversionService(superBw.getConversionService()); setSecurityContext(superBw.acc); } /** * Switch the target object, replacing the cached introspection results only * if the class of the new object is different to that of the replaced object. * @param object the new target object * @param nestedPath the nested path of the object * @param rootObject the root object at the top of the path */ public void setWrappedInstance(Object object, String nestedPath, Object rootObject) { Assert.notNull(object, "Bean object must not be null"); this.object = object; this.nestedPath = (nestedPath != null ? nestedPath : ""); this.rootObject = (!"".equals(this.nestedPath) ? rootObject : object); this.nestedBeanWrappers = null; this.typeConverterDelegate = new TypeConverterDelegate(this, object); setIntrospectionClass(object.getClass()); }
2.3 使用 BeanWrapper 设置&获取属性值(包含嵌套)
- PropertyTokenHolder
在了解 BeanWrapper 设置和获取获取属性值前,我们先了解一下 PropertyTokenHolder。PropertyTokenHolder 是 BeanWrapperImpl 的内部类,他很简单,定义了属性命名描述。一个能标识 Bean 的唯一名称(可能包含嵌套的路径),Bean 真实名称(不包含嵌套路径),访问集合属性的索引数组。
private static class PropertyTokenHolder { // 例如 BeanA 中有个 Set 属性,他们的名称是“xxxSet”, // 我们可以通过“xxxSet[1]”访问这个属性值,需要获得BeanA.xxxSet的一个值 // 权威唯一名称,例如:xxxSet[1] public String canonicalName; // 真实名称,例如:xxxSet public String actualName; // 访问集合索引,例如:["1"] public String[] keys; }
- 设置属性值
设置属性值,设置属性值有两个重载的方法可供选择。在设置属性时,需要处理嵌套属性的设置。此种需要了解 PropertyTokenHolder,他是一个内部简单类,定义了嵌套的名称、真实名称、对应的访问KEY三个属性。
@Override public void setPropertyValue(String propertyName, Object value) throws BeansException { BeanWrapperImpl nestedBw; try { // 此方法在下面介绍 nestedBw = getBeanWrapperForPropertyPath(propertyName); } catch (NotReadablePropertyException ex) { throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName, "Nested property in path '" + propertyName + "' does not exist", ex); } // getFinalPath 的处理逻辑是如果 nestedBw 是自己情况,直接返回传入的 propertyName PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName)); // 后面介绍这个方法 nestedBw.setPropertyValue(tokens, new PropertyValue(propertyName, value)); } @Override public void setPropertyValue(PropertyValue pv) throws BeansException { PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens; // 如果无法获取属性标识,重新计算一下 if (tokens == null) { String propertyName = pv.getName(); BeanWrapperImpl nestedBw; try { // 如果是嵌套的 BeanWrapper,获取的是嵌套的实例,否则是自己本身 nestedBw = getBeanWrapperForPropertyPath(propertyName); } catch (NotReadablePropertyException ex) { throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName, "Nested property in path '" + propertyName + "' does not exist", ex); } tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName)); if (nestedBw == this) { pv.getOriginalPropertyValue().resolvedTokens = tokens; } nestedBw.setPropertyValue(tokens, pv); } else { setPropertyValue(tokens, pv); } } @SuppressWarnings("unchecked") private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException { String propertyName = tokens.canonicalName; String actualName = tokens.actualName; // 如果标识中的 keys 不为空,说明属性是集合方式的,需要通过集合的方式处理 // 并且应该提供对应属性的 getter 方法,因为需要访问对应的集合 if (tokens.keys != null) { // Apply indexes and map keys: fetch value for all keys but the last one. PropertyTokenHolder getterTokens = new PropertyTokenHolder(); getterTokens.canonicalName = tokens.canonicalName; getterTokens.actualName = tokens.actualName; getterTokens.keys = new String[tokens.keys.length - 1]; System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1); Object propValue; try { // 获取对应属性值 propValue = getPropertyValue(getterTokens); } catch (NotReadablePropertyException ex) { throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName, "Cannot access indexed value in property referenced " + "in indexed property path '" + propertyName + "'", ex); } // Set value for last key. String key = tokens.keys[tokens.keys.length - 1]; if (propValue == null) { // null map value case if (this.autoGrowNestedPaths) { // TODO: cleanup, this is pretty hacky int lastKeyIndex = tokens.canonicalName.lastIndexOf('['); getterTokens.canonicalName = tokens.canonicalName.substring(0, lastKeyIndex); propValue = setDefaultValue(getterTokens); } else { throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName, "Cannot access indexed value in property referenced " + "in indexed property path '" + propertyName + "': returned null"); } } // 如果属性值是数组类型 if (propValue.getClass().isArray()) { PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName); Class requiredType = propValue.getClass().getComponentType(); int arrayIndex = Integer.parseInt(key); Object oldValue = null; try { if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) { oldValue = Array.get(propValue, arrayIndex); } Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType, TypeDescriptor.nested(property(pd), tokens.keys.length)); Array.set(propValue, arrayIndex, convertedValue); } catch (IndexOutOfBoundsException ex) { throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName, "Invalid array index in property path '" + propertyName + "'", ex); } } // 如果属性值是List类型 else if (propValue instanceof List) { PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName); Class requiredType = GenericCollectionTypeResolver.getCollectionReturnType( pd.getReadMethod(), tokens.keys.length); List list = (List) propValue; int index = Integer.parseInt(key); Object oldValue = null; if (isExtractOldValueForEditor() && index < list.size()) { oldValue = list.get(index); } Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType, TypeDescriptor.nested(property(pd), tokens.keys.length)); int size = list.size(); if (index >= size && index < this.autoGrowCollectionLimit) { for (int i = size; i < index; i++) { try { list.add(null); } catch (NullPointerException ex) { throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName, "Cannot set element with index " + index + " in List of size " + size + ", accessed using property path '" + propertyName + "': List does not support filling up gaps with null elements"); } } list.add(convertedValue); } else { try { list.set(index, convertedValue); } catch (IndexOutOfBoundsException ex) { throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName, "Invalid list index in property path '" + propertyName + "'", ex); } } } // 如果属性是Map类型 else if (propValue instanceof Map) { PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName); Class mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType( pd.getReadMethod(), tokens.keys.length); Class mapValueType = GenericCollectionTypeResolver.getMapValueReturnType( pd.getReadMethod(), tokens.keys.length); Map map = (Map) propValue; // IMPORTANT: Do not pass full property name in here - property editors // must not kick in for map keys but rather only for map values. TypeDescriptor typeDescriptor = (mapKeyType != null ? TypeDescriptor.valueOf(mapKeyType) : TypeDescriptor.valueOf(Object.class)); Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType, typeDescriptor); Object oldValue = null; if (isExtractOldValueForEditor()) { oldValue = map.get(convertedMapKey); } // Pass full property name and old value in here, since we want full // conversion ability for map values. Object convertedMapValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), mapValueType, TypeDescriptor.nested(property(pd), tokens.keys.length)); map.put(convertedMapKey, convertedMapValue); } // 其他是非集合情况,抛出异常 else { throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName, "Property referenced in indexed property path '" + propertyName + "' is neither an array nor a List nor a Map; returned value was [" + pv.getValue() + "]"); } } // 当标识中Key为空,此时需要直接设定属性的值 else { // 获取对应的属性描述 PropertyDescriptor pd = pv.resolvedDescriptor; // 如果无法获取属性描述,或者获得的属性描述对应的 class 不是被包装实例的class时,重新获取 if (pd == null || !pd.getWriteMethod().getDeclaringClass().isInstance(this.object)) { pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName); if (pd == null || pd.getWriteMethod() == null) { if (pv.isOptional()) { logger.debug("Ignoring optional value for property '" + actualName + "' - property not found on bean class [" + getRootClass().getName() + "]"); return; } else { PropertyMatches matches = PropertyMatches.forProperty(propertyName, getRootClass()); throw new NotWritablePropertyException( getRootClass(), this.nestedPath + propertyName, matches.buildErrorMessage(), matches.getPossibleMatches()); } } pv.getOriginalPropertyValue().resolvedDescriptor = pd; } Object oldValue = null; try { Object originalValue = pv.getValue(); Object valueToApply = originalValue; // 如果需要类型转换,需要对输入的属性值进行类型转换 if (!Boolean.FALSE.equals(pv.conversionNecessary)) { if (pv.isConverted()) { valueToApply = pv.getConvertedValue(); } else { // 如果存在 getter,从 getter 中获取对应的属性值,为了某些个性化的编辑器使用 if (isExtractOldValueForEditor() && pd.getReadMethod() != null) { final Method readMethod = pd.getReadMethod(); if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) && !readMethod.isAccessible()) { if (System.getSecurityManager()!= null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { readMethod.setAccessible(true); return null; } }); } else { readMethod.setAccessible(true); } } try { if (System.getSecurityManager() != null) { oldValue = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { return readMethod.invoke(object); } }, acc); } else { oldValue = readMethod.invoke(object); } } 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 + propertyName + "'", ex); } } } valueToApply = convertForProperty(propertyName, oldValue, originalValue, pd); } pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue); } // 获取 setter 方法 final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ? ((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() : pd.getWriteMethod()); if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) { if (System.getSecurityManager()!= null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { writeMethod.setAccessible(true); return null; } }); } else { writeMethod.setAccessible(true); } } // 设置处理后的值 final Object value = valueToApply; if (System.getSecurityManager() != null) { try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { writeMethod.invoke(object, value); return null; } }, acc); } catch (PrivilegedActionException ex) { throw ex.getException(); } } else { writeMethod.invoke(this.object, value); } } catch (TypeMismatchException ex) { throw ex; } catch (InvocationTargetException ex) { PropertyChangeEvent propertyChangeEvent = new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue()); if (ex.getTargetException() instanceof ClassCastException) { throw new TypeMismatchException(propertyChangeEvent, pd.getPropertyType(), ex.getTargetException()); } else { throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException()); } } catch (Exception ex) { PropertyChangeEvent pce = new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue()); throw new MethodInvocationException(pce, ex); } } } /** * 通过嵌套的属性路径递归查询 BeanWrapper 实例。 * Recursively navigate to return a BeanWrapper for the nested property path. * @param propertyPath property property path, which may be nested * @return a BeanWrapper for the target bean */ protected BeanWrapperImpl getBeanWrapperForPropertyPath(String propertyPath) { // 获取属性解析的位置,例如属性路径为“beanA.beanB”,此时获取的pos=5 // 如果参数中不包含“.”, pos=-1,这里取得的是第一个“.”的位置 int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(propertyPath); // Handle nested properties recursively. // 如果存在嵌套的情况,就需要递归查询,直到找到对应的 BeanWrapper 实例为止。 if (pos > -1) { // 得到的值为:beanA String nestedProperty = propertyPath.substring(0, pos); // 得到的值为:beanB String nestedPath = propertyPath.substring(pos + 1); // 通过 beanA 得到嵌套的 BeanWrapper 实例 BeanWrapperImpl nestedBw = getNestedBeanWrapper(nestedProperty); // 递归查询通过 beanA 得到嵌套的 BeanWrapper 实例的属性值 beanB return nestedBw.getBeanWrapperForPropertyPath(nestedPath); } // 如果不存在嵌套的情况,返回自己本身的引用 else { return this; } } /** * 为指定的嵌套属性恢复一个 BeanWrapper 实例,如果没有缓存中找到,重新创建一个。 * Retrieve a BeanWrapper for the given nested property. * Create a new one if not found in the cache. * <p>Note: Caching nested BeanWrappers is necessary now, * to keep registered custom editors for nested properties. * @param nestedProperty property to create the BeanWrapper for * @return the BeanWrapper instance, either cached or newly created */ private BeanWrapperImpl getNestedBeanWrapper(String nestedProperty) { // 如嵌套的 BeanWrapper 缓存为空,重建一个 if (this.nestedBeanWrappers == null) { this.nestedBeanWrappers = new HashMap<String, BeanWrapperImpl>(); } // Get value of bean property. PropertyTokenHolder tokens = getPropertyNameTokens(nestedProperty); String canonicalName = tokens.canonicalName; // 获取对应的属性值(留在后面讲解) Object propertyValue = getPropertyValue(tokens); if (propertyValue == null) { if (this.autoGrowNestedPaths) { propertyValue = setDefaultValue(tokens); } else { throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + canonicalName); } } // Lookup cached sub-BeanWrapper, create new one if not found. BeanWrapperImpl nestedBw = this.nestedBeanWrappers.get(canonicalName); if (nestedBw == null || nestedBw.getWrappedInstance() != propertyValue) { if (logger.isTraceEnabled()) { logger.trace("Creating new nested BeanWrapper for property '" + canonicalName + "'"); } // 构建一个新的 BeanWrapper 实例,把自己作为嵌套父类,嵌套路径=当前路径+嵌套Bean标识+“.” nestedBw = newNestedBeanWrapper(propertyValue, this.nestedPath + canonicalName + NESTED_PROPERTY_SEPARATOR); // Inherit all type-specific PropertyEditors. // 复制属性注册器到嵌套的 BeanWrapper 中 copyDefaultEditorsTo(nestedBw); copyCustomEditorsTo(nestedBw, canonicalName); // 嵌套 BeanWrapper 缓存添加新建的 BeanWrapper 实例 this.nestedBeanWrappers.put(canonicalName, nestedBw); } else { if (logger.isTraceEnabled()) { logger.trace("Using cached nested BeanWrapper for property '" + canonicalName + "'"); } } return nestedBw; } /** * 解析指定的属性名称,并把它赋值到对应的属性标识中(即保存在 PropertyTokenHolder 中) * Parse the given property name into the corresponding property name tokens. * @param propertyName the property name to parse * @return representation of the parsed property tokens */ private PropertyTokenHolder getPropertyNameTokens(String propertyName) { // 例如输入“xxxSet[1]” PropertyTokenHolder tokens = new PropertyTokenHolder(); String actualName = null; List<String> keys = new ArrayList<String>(2); int searchIndex = 0; while (searchIndex != -1) { // 从指定的索引位置查询“[”的位置 int keyStart = propertyName.indexOf(PROPERTY_KEY_PREFIX, searchIndex); searchIndex = -1; // 如果能找到,找对应的“]”的位置 if (keyStart != -1) { int keyEnd = propertyName.indexOf(PROPERTY_KEY_SUFFIX, keyStart + PROPERTY_KEY_PREFIX.length()); if (keyEnd != -1) { if (actualName == null) { // actualName = xxxSet actualName = propertyName.substring(0, keyStart); } // key = 1 String key = propertyName.substring(keyStart + PROPERTY_KEY_PREFIX.length(), keyEnd); if ((key.startsWith("'") && key.endsWith("'")) || (key.startsWith("\"") && key.endsWith("\""))) { key = key.substring(1, key.length() - 1); } keys.add(key); // 重置查询索取到“]”符号后面 searchIndex = keyEnd + PROPERTY_KEY_SUFFIX.length(); } } } // tokens.actualName = xxxSet tokens.actualName = (actualName != null ? actualName : propertyName); // tokens.canonicalName = xxxSet tokens.canonicalName = tokens.actualName; if (!keys.isEmpty()) { // tokens.canonicalName = xxxSet[1] tokens.canonicalName += PROPERTY_KEY_PREFIX + StringUtils.collectionToDelimitedString(keys, PROPERTY_KEY_SUFFIX + PROPERTY_KEY_PREFIX) + PROPERTY_KEY_SUFFIX; // tokens.keys = [1] tokens.keys = StringUtils.toStringArray(keys); } // 输入"xxxSet[1]",得到: // tokens.actualName="xxxSet",tokens.canonicalName="xxxSet[1]",tokens.keys=["1"] // 输入"xxxSet",得到: // tokens.actualName="xxxSet",tokens.canonicalName="xxxSet",tokens.keys=null return tokens; }
- 获取属性值
再来说说获取属性值,BeanWrapperImpl 提供了 getPropertyValue(String propertyName) 来处理。下面看看源码,了解实现方式:
@Override public Object getPropertyValue(String propertyName) throws BeansException { // 获取 propertyName 对应的 BeanWrapper 实例。如果包含嵌套,获取最后一层嵌套的 BeanWrapper 实例 BeanWrapperImpl nestedBw = getBeanWrapperForPropertyPath(propertyName); // 构建访问属性的 property 属性名称的标识 PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName)); // 执行获取属性值 return nestedBw.getPropertyValue(tokens); } private Object getPropertyValue(PropertyTokenHolder tokens) throws BeansException { String propertyName = tokens.canonicalName; String actualName = tokens.actualName; // 获取对应的属性描述定义 PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName); // 如果无法获取getter方法,直接异常 if (pd == null || pd.getReadMethod() == null) { throw new NotReadablePropertyException(getRootClass(), this.nestedPath + propertyName); } final Method readMethod = pd.getReadMethod(); try { // 如果 getter 访问不是 pulbic 类型,并且不是可以获取的,设置成可以访问 if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) && !readMethod.isAccessible()) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { readMethod.setAccessible(true); return null; } }); } else { readMethod.setAccessible(true); } } // 通过 getter 方法获取对应的属性值 Object value; if (System.getSecurityManager() != null) { try { value = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { return readMethod.invoke(object, (Object[]) null); } }, acc); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { value = readMethod.invoke(object, (Object[]) null); } // 如果需要获取具体集合中某项值,指定了keys if (tokens.keys != null) { if (value == null) { // 如果设置了自动生成嵌套的值属性,设置默认值 if (this.autoGrowNestedPaths) { value = setDefaultValue(tokens.actualName); } else { throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName, "Cannot access indexed value of property referenced in indexed " + "property path '" + propertyName + "': returned null"); } } String indexedPropertyName = tokens.actualName; // apply indexes and map keys for (int i = 0; i < tokens.keys.length; i++) { String key = tokens.keys[i]; // 如果属性值为 null,抛出异常 if (value == null) { throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName, "Cannot access indexed value of property referenced in indexed " + "property path '" + propertyName + "': returned null"); } // 如果对应的属性是数组类型 else if (value.getClass().isArray()) { int index = Integer.parseInt(key); value = growArrayIfNecessary(value, index, indexedPropertyName); value = Array.get(value, index); } // 如果对应的属性是List类型 else if (value instanceof List) { int index = Integer.parseInt(key); List list = (List) value; growCollectionIfNecessary(list, index, indexedPropertyName, pd, i + 1); value = list.get(index); } // 如果对应的属性是Set类型 else if (value instanceof Set) { // Apply index to Iterator in case of a Set. Set set = (Set) value; int index = Integer.parseInt(key); if (index < 0 || index >= set.size()) { throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName, "Cannot get element with index " + index + " from Set of size " + set.size() + ", accessed using property path '" + propertyName + "'"); } Iterator it = set.iterator(); for (int j = 0; it.hasNext(); j++) { Object elem = it.next(); if (j == index) { value = elem; break; } } } // 如果对应的属性是Map类型 else if (value instanceof Map) { Map map = (Map) value; Class<?> mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(pd.getReadMethod(), i + 1); // IMPORTANT: Do not pass full property name in here - property editors // must not kick in for map keys but rather only for map values. TypeDescriptor typeDescriptor = mapKeyType != null ? TypeDescriptor.valueOf(mapKeyType) : TypeDescriptor.valueOf(Object.class); Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType, typeDescriptor); value = map.get(convertedMapKey); } // 其他情况,不是集合类型,不支持,抛出异常 else { throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName, "Property referenced in indexed property path '" + propertyName + "' is neither an array nor a List nor a Set nor a Map; returned value was [" + value + "]"); } indexedPropertyName += PROPERTY_KEY_PREFIX + key + PROPERTY_KEY_SUFFIX; } } return value; } catch (IndexOutOfBoundsException ex) { throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName, "Index of out of bounds in property path '" + propertyName + "'", ex); } catch (NumberFormatException ex) { throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName, "Invalid index in property path '" + propertyName + "'", ex); } catch (TypeMismatchException ex) { throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName, "Invalid index in property path '" + propertyName + "'", ex); } catch (InvocationTargetException ex) { throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName, "Getter for property '" + actualName + "' threw exception", ex); } catch (Exception ex) { throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName, "Illegal attempt to get property '" + actualName + "' threw exception", ex); } }
通过上面的代码分析,我们了解了 BeanWrapper 是如何获取属性值以及设置属性值的。同时 BeanWrapperImpl 通过定义嵌套路径来解析我们真正的需要的属性,并且智能的来判断我们意图。值得一提的是,对比设置方法和获取方法,我们会发现在设置方法中其并没有对 Set 进行处理,但是我可以通过 Set[index] 来获取对应的值。这是因为 Set 是要去重的,在设置的时候无法判断他的索引位置,但是在获取的时候可以通过遍历来获取对应 index 的值。
2.5 BeanWrapper 中类型转换
上面在分析设置 Bean 属性值时,使用了 convertIfNecessary 方法,这个方法中会判断是否需要类型转换。下面我们来分析这个类型转换。
- 类型转换代理实例构建
BeanWrapperImpl 中的类型转换是通过 TypeConverterDelegate 来实现的。构建这个实例发生在我们构建 BeanWrapper 实例的时候。
public BeanWrapperImpl(boolean registerDefaultEditors) { if (registerDefaultEditors) { registerDefaultEditors(); } this.typeConverterDelegate = new TypeConverterDelegate(this); } public void setWrappedInstance(Object object, String nestedPath, Object rootObject) { Assert.notNull(object, "Bean object must not be null"); this.object = object; this.nestedPath = (nestedPath != null ? nestedPath : ""); this.rootObject = (!"".equals(this.nestedPath) ? rootObject : object); this.nestedBeanWrappers = null; this.typeConverterDelegate = new TypeConverterDelegate(this, object); setIntrospectionClass(object.getClass()); }
- 类型转换
TypeConverterDelegate 重要提供的服务是 convertIfNecessary 。这个方法提供了几个重载方法,如下:
/** * Convert the value to the specified required type. * @param newValue the proposed new value * @param requiredType the type we must convert to * (or <code>null</code> if not known, for example in case of a collection element) * @param methodParam the method parameter that is the target of the conversion * (may be <code>null</code>) * @return the new value, possibly the result of type conversion * @throws IllegalArgumentException if type conversion failed */ public <T> T convertIfNecessary(Object newValue, Class<T> requiredType, MethodParameter methodParam) throws IllegalArgumentException { return convertIfNecessary(null, null, newValue, requiredType, (methodParam != null ? new TypeDescriptor(methodParam) : TypeDescriptor.valueOf(requiredType))); } /** * Convert the value to the required type for the specified property. * @param propertyName name of the property * @param oldValue the previous value, if available (may be <code>null</code>) * @param newValue the proposed new value * @param requiredType the type we must convert to * (or <code>null</code> if not known, for example in case of a collection element) * @return the new value, possibly the result of type conversion * @throws IllegalArgumentException if type conversion failed */ public <T> T convertIfNecessary( String propertyName, Object oldValue, Object newValue, Class<T> requiredType) throws IllegalArgumentException { return convertIfNecessary(propertyName, oldValue, newValue, requiredType, TypeDescriptor.valueOf(requiredType)); } /** * Convert the value to the required type (if necessary from a String), * for the specified property. * @param propertyName name of the property * @param oldValue the previous value, if available (may be <code>null</code>) * @param newValue the proposed new value * @param requiredType the type we must convert to * (or <code>null</code> if not known, for example in case of a collection element) * @param typeDescriptor the descriptor for the target property or field * @return the new value, possibly the result of type conversion * @throws IllegalArgumentException if type conversion failed */ @SuppressWarnings("unchecked") public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue, Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException { Object convertedValue = newValue; // Custom editor for this type? // 查找匹配的 PropertyEditor PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName); ConversionFailedException firstAttemptEx = null; // No custom editor but custom ConversionService specified? // 如果没有自定义的 PropertyEditor,但是定义了转换服务(conversionService) ConversionService conversionService = this.propertyEditorRegistry.getConversionService(); if (editor == null && conversionService != null && convertedValue != null && typeDescriptor != null) { TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue); TypeDescriptor targetTypeDesc = typeDescriptor; if (conversionService.canConvert(sourceTypeDesc, targetTypeDesc)) { try { return (T) conversionService.convert(convertedValue, sourceTypeDesc, targetTypeDesc); } // 如果无法转换成功,走下面的默认处理逻辑 catch (ConversionFailedException ex) { // fallback to default conversion logic below firstAttemptEx = ex; } } } // Value not of required type? // 如果找到了 PropertyEditor,或者提供转换的新值不是指定的转换类型 if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) { // 如果目标类型是集合类型,并且对应的值是 string 类型 if (requiredType != null && Collection.class.isAssignableFrom(requiredType) && convertedValue instanceof String) { TypeDescriptor elementType = typeDescriptor.getElementTypeDescriptor(); // 处理枚举类型集合 if (elementType != null && Enum.class.isAssignableFrom(elementType.getType())) { convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue); } } // 如果对应自定义的 PropertyEditer,使用默认的 PropertyEditor if (editor == null) { editor = findDefaultEditor(requiredType, typeDescriptor); } // 执行类型转换,获取转换后的值 convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor); } // 如果定义了需要转换的类型 if (requiredType != null) { // Try to apply some standard type conversion rules if appropriate. // 如果标准的的转换规则存在,尝试去适配标准的转换器 // 如果通过上面的转换(有自定义的转换或者需要转换的的值不是目标类型)能够得到转换后的值 if (convertedValue != null) { // 如果是数组,通过数组转换返回 // 如果对应的值是 spring,指定的转换数组的内部类型是枚举,用逗号分隔值 if (requiredType.isArray()) { // Array required -> apply appropriate conversion of elements. if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) { convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue); } return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType()); } // 如果对应的转换值是集合类型,通过集合转换 else if (convertedValue instanceof Collection) { // Convert elements to target type, if determined. convertedValue = convertToTypedCollection( (Collection) convertedValue, propertyName, requiredType, typeDescriptor); } // 如果对应的转换值是Map类型,通过Map转换器转换 else if (convertedValue instanceof Map) { // Convert keys and values to respective target type, if determined. convertedValue = convertToTypedMap( (Map) convertedValue, propertyName, requiredType, typeDescriptor); } // 如果对应的转换类型不是数组类型,对应的值是数组类型,取第一个值作为转换值 if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) { convertedValue = Array.get(convertedValue, 0); } // 如果对应转换类型是String类型,转化值是标准内部类型,直接转换为string返回 if (String.class.equals(requiredType) && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) { // We can stringify any primitive value... return (T) convertedValue.toString(); } // 处理枚举类型,值是枚举对应的名称 else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) { if (!requiredType.isInterface() && !requiredType.isEnum()) { try { Constructor strCtor = requiredType.getConstructor(String.class); return (T) BeanUtils.instantiateClass(strCtor, convertedValue); } catch (NoSuchMethodException ex) { // proceed with field lookup if (logger.isTraceEnabled()) { logger.trace("No String constructor found on type [" + requiredType.getName() + "]", ex); } } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Construction via String failed for type [" + requiredType.getName() + "]", ex); } } } String trimmedValue = ((String) convertedValue).trim(); if (requiredType.isEnum() && "".equals(trimmedValue)) { // It's an empty enum identifier: reset the enum value to null. return null; } convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue); } } // 如果转换后的值不是指定的转换类型,异常 if (!ClassUtils.isAssignableValue(requiredType, convertedValue)) { if (firstAttemptEx != null) { throw firstAttemptEx; } // Definitely doesn't match: throw IllegalArgumentException/IllegalStateException StringBuilder msg = new StringBuilder(); msg.append("Cannot convert value of type [").append(ClassUtils.getDescriptiveType(newValue)); msg.append("] to required type [").append(ClassUtils.getQualifiedName(requiredType)).append("]"); if (propertyName != null) { msg.append(" for property '").append(propertyName).append("'"); } if (editor != null) { msg.append(": PropertyEditor [").append(editor.getClass().getName()).append( "] returned inappropriate value of type [").append( ClassUtils.getDescriptiveType(convertedValue)).append("]"); throw new IllegalArgumentException(msg.toString()); } else { msg.append(": no matching editors or conversion strategy found"); throw new IllegalStateException(msg.toString()); } } } if (firstAttemptEx != null) { if (editor == null && convertedValue == newValue) { throw firstAttemptEx; } logger.debug("Original ConversionService attempt failed - ignored since " + "PropertyEditor based conversion eventually succeeded", firstAttemptEx); } return (T) convertedValue; }
3. 实例化的各个流程
再次回顾一下上次分享中的 Bean 依赖注入的大概过程:
BeanFactory.getBean → AbstarctBeanFactory.doGetBean → AbstractAutowireCapableBeanFactory.createBean
中间会递归查询依赖,从而完成 Bean 的依赖注入过程。这个过程也是 Bean 实例化过程。
3.1 创建Bean实例
创建 Bean 实例当调用到 AbstractAutowireCapableBeanFactory.createBean 方法后,会转发到 AbstractAutowireCapableBeanFactory.doCreateBean 方法。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { // Instantiate the bean. // 初始化 Bean 实例,创建 Bean 实例的 BeanWrapper。 // 如果是单例,需要从容器实例缓存中获取,并删除缓存 BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); // Allow post-processors to modify the merged bean definition. // 给你一次修改 bean 定义的机会,同时你可以来检查bean定义的相关属性 synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. // 可以做代理,改变Bean的引用的地方(SmartInstantiationAwareBeanPostProcessor) boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, new ObjectFactory() { public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); } // Initialize the bean instance. Object exposedObject = bean; try { // 组装 Bean,后面会讲到 populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd); } } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } // 二次验证提前暴露引用(SmartInstantiationAwareBeanPostProcessor)的处理是否正确 if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } } } } // Register bean as disposable. try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; } /** * 通过指定的实例化策略初始化一个新的的 Bean 实例。初始化策略:工厂方法、自动装载构造方法、默认简单构造方法 * Create a new instance for the specified bean, using an appropriate instantiation strategy: * factory method, constructor autowiring, or simple instantiation. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param args arguments to use if creating a prototype using explicit arguments to a * static factory method. It is invalid to use a non-null args value in any other case. * @return BeanWrapper for the new instance * @see #instantiateUsingFactoryMethod * @see #autowireConstructor * @see #instantiateBean */ protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { // Make sure bean class is actually resolved at this point. Class beanClass = resolveBeanClass(mbd, beanName); if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); } // 如果配置了通过工厂方法构造,查找对应的工厂方法来初始化 Bean 实例 if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // Shortcut when re-creating the same bean… // 如果是重新创建同一个 bean,可以根据 BeanDefinition 中的标识来判断 boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } // 如果已经通过构造方法或者的构造工厂处理过 bean 定义 if (resolved) { if (autowireNecessary) { return autowireConstructor(beanName, mbd, null, null); } else { return instantiateBean(beanName, mbd); } } // 剩下的就是需要去查询使用那个构造方法,如果能找到对应的构造方法,使用构造方法来创建实例, // 否则就是使用默认构造方法。例如经常使用的默认无参数构造方法 // Need to determine the constructor… // 如果定义了对应的 BeanPostProcessor,定义使用某个构造方法,使用之 Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // No special handling: simply use no-arg constructor. // 默认使用无参数构造方法 return instantiateBean(beanName, mbd); }
4. 自动注入实现方式
4.1 组装 Bean
你已经厌倦了上面上面长篇的累述,你还没有了解到 BeanWrapper 和组装 Bean 的用途,那么我可以高兴的告诉你,下面我就分析 Bean 的组装,了解 BeanWrapper 的用途。当了解完这个下面这个方法后,我们这次的分享就基本上结束了。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean:
/** * 根据 BeanWrapper,来组装 Bean 实例 * 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 BeanWrapper with bean instance */ protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) { // 从 BeanDefinition 中获取所有的的 Bean 属性 PropertyValues pvs = mbd.getPropertyValues(); // 如果没有指定 BeanWrapper,但是有 Bean 属性,异常返回,否则跳过处理 if (bw == null) { if (!pvs.isEmpty()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. boolean continueWithPropertyPopulation = true; // 给你一次扩展的 BeanPostProcessor 的机会,来在 Bean 实例化后做点儿自己想干的事情 // 回想一下对应的 InstantiationAwareBeanPostProcessor 什么时间会在初始化前调用? if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } // 处理根据名称自动转载和根据类型自动装载的过程 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. // 根据名称增加属性的装载 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. // 根据类型增加属性的装载 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); // 在 Bean 发布可以使用前,检查依赖是否完整等 // 如果定义了InstantiationAwareBeanPostProcessor,你可以自定义自己的检查逻辑 // 也可以强制加载自己的依赖,例如注解 Resource 的实现等。 if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw); 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) { checkDependencies(beanName, mbd, filteredPds, pvs); } } // 对Bean相关的属性开始发布赋值,可能递归 getBean。 applyPropertyValues(beanName, mbd, bw, pvs); } /** * 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 == null || pvs.isEmpty()) { return; } MutablePropertyValues mpvs = null; List<PropertyValue> original; if (System.getSecurityManager()!= null) { if (bw instanceof BeanWrapperImpl) { ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); } } // 获取属性列表 if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; if (mpvs.isConverted()) { // Shortcut: use the pre-converted values as-is. 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; } // 构建对应的属性值处理器 // 属性值处理器,主要完成对应对依赖的属性的构建 BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // Create a deep copy, resolving any references for values. List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(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); } // Possibly store converted value in merged bean definition, // in order to avoid re-conversion for every created bean instance. 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.setConverted(); } // Set our (possibly massaged) deep copy. try { // 通过 BeanWrapper 来把所有的属性值赋值 bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } }
4.2 详解各个自动注入代码
属性名称自动装载
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); if (logger.isDebugEnabled()) { logger.debug("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"); } } } }
属性类型自动装载
protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } Set<String> autowiredBeanNames = new LinkedHashSet<String>(4); String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { try { 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.equals(pd.getPropertyType())) { MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd); // Do not allow eager init for type matching in case of a prioritized post-processor. boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass()); DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter); 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); } } }
5. 小结
通过上面的分享,我们了解了 Bean 创建过程。一般情况下,我们会使用构造函数或者setter方法来进行依赖。BeanWrapper能很好的处理getter和setter方式;构造方法、工厂方法的形式构建 bean, Spring也做了很好的处理。但是我们常用“Resouce”方式,即没有构造方法、也没有setter方法,又该如何处理呢?这个留在下一次分享,关于 BeanPostProcessor。
相关推荐
### Spring IoC与注解依赖注入详解 #### 一、Spring框架简介 Spring框架是由Rod Johnson创建的一个开源项目,最初是为了解决企业级应用开发中的复杂性问题而诞生的。Spring框架的核心特性包括IoC(Inversion of ...
4. **依赖注入**: 在实例化Bean的同时,Spring会根据Bean定义中的依赖关系,自动将所需的其他Bean注入到当前Bean中。依赖注入可以通过属性注入(setter方法)、构造器注入或者方法注入实现。 5. **生命周期管理**: ...
Bean 的生命周期流程包括实例化、依赖注入、初始化、使用、销毁等阶段。在 Bean 的生命周期中,我们需要了解 Bean 的生命周期案例,以便更好地理解 Bean 的生命周期。 本文主要研究了 Spring 框架中 Bean 的实例化...
Spring_IOC-v(上)笔记是关于 Spring 框架中的 IoC(控制反转)技术的笔记,主要介绍了 IoC 的概念、依赖注入、Bean 的设置、Spring 组件的管理等知识点。 IoC 技术是 Spring 框架的核心概念之一,它的主要思想...
总结来说,BeanDefinition是Spring IoC容器的核心组成部分,它封装了bean的所有配置信息,使容器能够根据这些信息实例化、配置、管理bean,从而实现了控制反转。通过XML配置文件,我们可以轻松地定义bean及其属性,...
4. **启动后处理器(BeanPostProcessor)**:这些是特殊类型的Bean,它们在所有常规Bean实例化之后,但初始化之前进行处理。它们的实例化顺序由`@Order`注解决定,或者通过实现`Ordered`接口来控制。 5. **...
工厂Bean允许开发者在对象实例化时进行更复杂的控制,比如引入特定的初始化过程、依赖注入或者资源管理。这篇博文将深入探讨工厂Bean的工作原理和使用场景。 首先,让我们理解什么是Bean。在Spring中,Bean是IoC...
浅谈Spring IoC容器的依赖注入...Spring IoC容器的依赖注入原理是通过IoC容器初始化和Bean实例化两个阶段来实现的。在这个过程中,IoC容器会根据Bean的依赖关系来实例化和提供Bean对象,从而实现了自动依赖注入机制。
2. **Bean实例化**:根据BeanDefinition,Spring容器创建Bean实例,可以是单例或多例。 3. **依赖注入**:Spring容器根据BeanDefinition中的依赖关系,为Bean注入依赖对象。 4. **初始化**:Spring容器调用Bean的...
这里,`init-method`指定的`initMethod`方法会在Bean实例化后被调用。 除了XML配置,Spring还支持基于注解的配置,如`@Component`、`@Service`、`@Repository`和`@Controller`,以及`@Autowired`用于自动装配依赖。...
Spring Ioc 源码分析系列--自动注入循环依赖的处理 本篇文章主要讲解了 Spring Ioc 源码分析系列中自动注入循环依赖的处理机制。循环依赖是 Spring 框架中一个经典的问题,也是面试中常被问到的问题。本篇文章将...
Spring IoC容器通过XML配置或注解实现了对象的创建、管理和依赖注入,极大地简化了Java应用的复杂性。理解并熟练运用Spring IoC,能够帮助开发者构建更灵活、易于测试和维护的系统。在实际开发中,还可以结合@...
学习Spring IOC Annotation注入,首先需要理解Bean的生命周期,包括初始化、使用和销毁的过程。然后,通过编写带有注解的类,创建Bean定义,并让Spring容器管理这些Bean。容器会在适当的时间调用`@PostConstruct`...
在传统的编程模式中,开发者需要手动创建和管理对象,而在Spring IOC中,这个过程被反转,由Spring容器负责对象的创建、初始化、装配以及管理,开发者只需声明对象间的依赖,无需关心具体的实例化过程。 1. **Bean...
Spring 框架是 Java 开发中不可或缺的一部分,它以其强大的依赖注入(Dependency Injection, DI)和控制反转(Inversion of Control, IOC)特性而闻名。在这个名为“spring-demo02-IOC-DI案例”的压缩包中,我们将...
Spring IoC通过XML配置文件实现了对象的实例化和依赖注入,有效地降低了对象间的耦合,提高了代码的可读性和可维护性。理解并熟练运用Spring的IoC机制是成为一名优秀的Java开发者的关键步骤之一。在实际项目中,结合...
通过构造器或工厂方法创建Bean实例 为Bean的属性设置值和对其它Bean的引用 调用Bean的初始化方法 Bean可以使用了 当容器关闭时,调用Bean的销毁方法 在 Bean 的声明里设置 init-method 和 destroy-method 属性, 为 ...
进入`doGetBean()`方法,这是Bean实例化的关键步骤。`doGetBean()`会处理Bean的依赖注入、类型检查等操作。 7. **创建Bean**: `createBean(beanName, mbd, args)`在`AbstractAutowireCapableBeanFactory`中实现...