1. 程式人生 > >Spring IOC原始碼詳解之容器依賴注入

Spring IOC原始碼詳解之容器依賴注入

進入BeanWrapperImpl
public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements BeanWrapper

BeanWrapperImpl繼承了AbstractNestablePropertyAccessor,對應的setPropertyValues方法也在AbstractNestablePropertyAccessor中,進入AbstractNestablePropertyAccessor

裡面有三個setPropertyValues方法,前兩個都指向了最後一個:

//實現屬性依賴注入功能  
   private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {  
       //PropertyTokenHolder主要儲存屬性的名稱、路徑,以及集合的size等資訊  
       String propertyName = tokens.canonicalName;  
       String actualName = tokens.actualName;  
       //keys是用來儲存集合型別屬性的size  
       if (tokens.keys != null) {  
           //將屬性資訊拷貝  
           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 {  
               //獲取屬性值,該方法內部使用JDK的內省( Introspector)機制,呼叫屬性//的getter(readerMethod)方法,獲取屬性的值  
               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);  
           }  
           //獲取集合型別屬性的長度  
           String key = tokens.keys[tokens.keys.length - 1];  
           if (propValue == null) {  
               throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,  
                       "Cannot access indexed value in property referenced " +  
                       "in indexed property path '" + propertyName + "': returned null");  
           }  
           //注入array型別的屬性值  
           else 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()) {  
                       oldValue = Array.get(propValue, arrayIndex);  
                   }  
                   //將屬性的值賦值給陣列中的元素  
                   Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,  
                           new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), requiredType));  
                   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);  
               //獲取list集合的型別  
               Class requiredType = GenericCollectionTypeResolver.getCollectionReturnType(  
                       pd.getReadMethod(), tokens.keys.length);  
               List list = (List) propValue;  
               //獲取list集合的size  
               int index = Integer.parseInt(key);  
               Object oldValue = null;  
               if (isExtractOldValueForEditor() && index < list.size()) {  
                   oldValue = list.get(index);  
               }  
               //獲取list解析後的屬性值  
               Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,  
                       new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), requiredType));  
               if (index < list.size()) {  
                   //為list屬性賦值  
                   list.set(index, convertedValue);  
               }  
               //如果list的長度大於屬性值的長度,則多餘的元素賦值為null  
               else if (index >= list.size()) {  
                   for (int i = list.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 " +  
                                   list.size() + ", accessed using property path '" + propertyName +  
                                   "': List does not support filling up gaps with null elements");  
                       }  
                   }  
                   list.add(convertedValue);  
               }  
           }  
           //注入map型別的屬性值  
           else if (propValue instanceof Map) {  
               PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);  
               //獲取map集合key的型別  
               Class mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(  
                       pd.getReadMethod(), tokens.keys.length);  
               //獲取map集合value的型別  
               Class mapValueType = GenericCollectionTypeResolver.getMapValueReturnType(  
                       pd.getReadMethod(), tokens.keys.length);  
               Map map = (Map) propValue;  
               //解析map型別屬性key值  
               Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType,  
                       new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), mapKeyType));  
               Object oldValue = null;  
               if (isExtractOldValueForEditor()) {  
                   oldValue = map.get(convertedMapKey);  
               }  
               //解析map型別屬性value值  
               Object convertedMapValue = convertIfNecessary(  
                       propertyName, oldValue, pv.getValue(), mapValueType,  
                       new TypeDescriptor(new MethodParameter(pd.getReadMethod(), -1, tokens.keys.length + 1)));  
               //將解析後的key和value值賦值給map集合屬性  
               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() + "]");  
           }  
       }  
       //對非集合型別的屬性注入  
       else {  
           PropertyDescriptor pd = pv.resolvedDescriptor;  
           if (pd == null || !pd.getWriteMethod().getDeclaringClass().isInstance(this.object)) {  
               pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);  
               //無法獲取到屬性名或者屬性沒有提供setter(寫方法)方法  
               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;  
                   }  
                   //如果屬性值是必須的,則丟擲無法給屬性賦值,因為每天提供setter方法異常  
                   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 {  
                       if (isExtractOldValueForEditor() && pd.getReadMethod() != null) {  
                           //獲取屬性的getter方法(讀方法),JDK內省機制  
                           final Method readMethod = pd.getReadMethod();  
                           //如果屬性的getter方法不是public訪問控制權限的,即訪問控制權限比較嚴格,  
                           //則使用JDK的反射機制強行訪問非public的方法(暴力讀取屬性值)  
                           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 {  
                               //屬性沒有提供getter方法時,呼叫潛在的讀取屬性值//的方法,獲取屬性值  
                               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);  
               }  
               //根據JDK的內省機制,獲取屬性的setter(寫方法)方法  
               final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ?  
                       ((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() :  
                       pd.getWriteMethod());  
               //如果屬性的setter方法是非public,即訪問控制權限比較嚴格,則使用JDK的反射機制,  
               //強行設定setter方法可訪問(暴力為屬性賦值)  
               if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {  
                   //如果使用了JDK的安全機制,則需要許可權驗證  
                   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);  
           }  
       }  
    }

有上面分析,Spring IoC容器將屬性的值注入到Bean例項物件中大致如下

  • 對於集合型別的屬性,將其屬性值解析為目標型別的集合後直接賦值給屬性

  • 對於非集合型別的屬性,大量使用了JDK的反射和內省機制,通過屬性的getter方法(reader method)獲取指定屬性注入以前的值,同時呼叫屬性的setter方法(writer method)為屬性設定注入後的值。

至此,SpringIOC依賴注入就基本到這裡了