Spring:原始碼解讀Spring IOC原理
阿新 • • 發佈:2018-12-30
1 //實現屬性依賴注入功能
2 private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
3 //PropertyTokenHolder主要儲存屬性的名稱、路徑,以及集合的size等資訊
4 String propertyName = tokens.canonicalName;
5 String actualName = tokens.actualName;
6 // keys是用來儲存集合型別屬性的size
7 if (tokens.keys != null) {
8 //將屬性資訊拷貝
9 PropertyTokenHolder getterTokens = new PropertyTokenHolder();
10 getterTokens.canonicalName = tokens.canonicalName;
11 getterTokens.actualName = tokens.actualName;
12 getterTokens.keys = new String[tokens.keys.length - 1];
13 System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);
14 Object propValue;
15 try {
16 //獲取屬性值,該方法內部使用JDK的內省( Introspector)機制,呼叫屬性//的getter(readerMethod)方法,獲取屬性的值
17 propValue = getPropertyValue(getterTokens);
18 }
19 catch (NotReadablePropertyException ex) {
20 throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
21 "Cannot access indexed value in property referenced " +
22 "in indexed property path '" + propertyName + "'", ex);
23 }
24 //獲取集合型別屬性的長度
25 String key = tokens.keys[tokens.keys.length - 1];
26 if (propValue == null) {
27 throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,
28 "Cannot access indexed value in property referenced " +
29 "in indexed property path '" + propertyName + "': returned null");
30 }
31 //注入array型別的屬性值
32 else if (propValue.getClass().isArray()) {
33 //獲取屬性的描述符
34 PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
35 //獲取陣列的型別
36 Class requiredType = propValue.getClass().getComponentType();
37 //獲取陣列的長度
38 int arrayIndex = Integer.parseInt(key);
39 Object oldValue = null;
40 try {
41 //獲取陣列以前初始化的值
42 if (isExtractOldValueForEditor()) {
43 oldValue = Array.get(propValue, arrayIndex);
44 }
45 //將屬性的值賦值給陣列中的元素
46 Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,
47 new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), requiredType));
48 Array.set(propValue, arrayIndex, convertedValue);
49 }
50 catch (IndexOutOfBoundsException ex) {
51 throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
52 "Invalid array index in property path '" + propertyName + "'", ex);
53 }
54 }
55 //注入list型別的屬性值
56 else if (propValue instanceof List) {
57 PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
58 //獲取list集合的型別
59 Class requiredType = GenericCollectionTypeResolver.getCollectionReturnType(
60 pd.getReadMethod(), tokens.keys.length);
61 List list = (List) propValue;
62 //獲取list集合的size
63 int index = Integer.parseInt(key);
64 Object oldValue = null;
65 if (isExtractOldValueForEditor() && index < list.size()) {
66 oldValue = list.get(index);
67 }
68 //獲取list解析後的屬性值
69 Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,
70 new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), requiredType));
71 if (index < list.size()) {
72 //為list屬性賦值
73 list.set(index, convertedValue);
74 }
75 //如果list的長度大於屬性值的長度,則多餘的元素賦值為null
76 else if (index >= list.size()) {
77 for (int i = list.size(); i < index; i++) {
78 try {
79 list.add(null);
80 }
81 catch (NullPointerException ex) {
82 throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
83 "Cannot set element with index " + index + " in List of size " +
84 list.size() + ", accessed using property path '" + propertyName +
85 "': List does not support filling up gaps with null elements");
86 }
87 }
88 list.add(convertedValue);
89 }
90 }
91 //注入map型別的屬性值
92 else if (propValue instanceof Map) {
93 PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
94 //獲取map集合key的型別
95 Class mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(
96 pd.getReadMethod(), tokens.keys.length);
97 //獲取map集合value的型別
98 Class mapValueType = GenericCollectionTypeResolver.getMapValueReturnType(
99 pd.getReadMethod(), tokens.keys.length);
100 Map map = (Map) propValue;
101 //解析map型別屬性key值
102 Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType,
103 new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), mapKeyType));
104 Object oldValue = null;
105 if (isExtractOldValueForEditor()) {
106 oldValue = map.get(convertedMapKey);
107 }
108 //解析map型別屬性value值
109 Object convertedMapValue = convertIfNecessary(
110 propertyName, oldValue, pv.getValue(), mapValueType,
111 new TypeDescriptor(new MethodParameter(pd.getReadMethod(), -1, tokens.keys.length + 1)));
112 //將解析後的key和value值賦值給map集合屬性
113 map.put(convertedMapKey, convertedMapValue);
114 }
115 else {
116 throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
117 "Property referenced in indexed property path '" + propertyName +
118 "' is neither an array nor a List nor a Map; returned value was [" + pv.getValue() + "]");
119 }
120 }
121 //對非集合型別的屬性注入
122 else {
123 PropertyDescriptor pd = pv.resolvedDescriptor;
124 if (pd == null || !pd.getWriteMethod().getDeclaringClass().isInstance(this.object)) {
125 pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
126 //無法獲取到屬性名或者屬性沒有提供setter(寫方法)方法
127 if (pd == null || pd.getWriteMethod() == null) {
128 //如果屬性值是可選的,即不是必須的,則忽略該屬性值
129 if (pv.isOptional()) {
130 logger.debug("Ignoring optional value for property '" + actualName +
131 "' - property not found on bean class [" + getRootClass().getName() + "]");
132 return;
133 }
134 //如果屬性值是必須的,則丟擲無法給屬性賦值,因為每天提供setter方法異常
135 else {
136 PropertyMatches matches = PropertyMatches.forProperty(propertyName, getRootClass());
137 throw new NotWritablePropertyException(
138 getRootClass(), this.nestedPath + propertyName,
139 matches.buildErrorMessage(), matches.getPossibleMatches());
140 }
141 }
142 pv.getOriginalPropertyValue().resolvedDescriptor = pd;
143 }
144 Object oldValue = null;
145 try {
146 Object originalValue = pv.getValue();
147 Object valueToApply = originalValue;
148 if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
149 if (pv.isConverted()) {
150 valueToApply = pv.getConvertedValue();
151 }
152 else {
153 if (isExtractOldValueForEditor() && pd.getReadMethod() != null) {
154 //獲取屬性的getter方法(讀方法),JDK內省機制
155 final Method readMethod = pd.getReadMethod();
156 //如果屬性的getter方法不是public訪問控制權限的,即訪問控制權限比較嚴格,
157 //則使用JDK的反射機制強行訪問非public的方法(暴力讀取屬性值)
158 if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) &&
159 !readMethod.isAccessible()) {
160 if (System.getSecurityManager()!= null) {
161 //匿名內部類,根據許可權修改屬性的讀取控制限制
162 AccessController.doPrivileged(new PrivilegedAction<Object>() {
163 public Object run() {
164 readMethod.setAccessible(true);
165 return null;
166 }
167 });
168 }
169 else {
170 readMethod.setAccessible(true);
171 }
172 }
173 try {
174 //屬性沒有提供getter方法時,呼叫潛在的讀取屬性值//的方法,獲取屬性值
175 if (System.getSecurityManager() != null) {
176 oldValue = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
177 public Object run() throws Exception {
178 return readMethod.invoke(object);
179 }
180 }, acc);
181 }
182 else {
183 oldValue = readMethod.invoke(object);
184 }
185 }
186 catch (Exception ex) {
187 if (ex instanceof PrivilegedActionException) {
188 ex = ((PrivilegedActionException) ex).getException();
189 }
190 if (logger.isDebugEnabled()) {
191 logger.debug("Could not read previous value of property '" +
192 this.nestedPath + propertyName + "'", ex);
193 }
194 }
195 }
196 //設定屬性的注入值
197 valueToApply = convertForProperty(propertyName, oldValue, originalValue, pd);
198 }
199 pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
200 }
201 //根據JDK的內省機制,獲取屬性的setter(寫方法)方法
202 final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ?
203 ((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() :
204 pd.getWriteMethod());
205 //如果屬性的setter方法是非public,即訪問控制權限比較嚴格,則使用JDK的反射機制,
206 //強行設定setter方法可訪問(暴力為屬性賦值)
207 if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {
208 //如果使用了JDK的安全機制,則需要許可權驗證
209 if (System.getSecurityManager()!= null) {
210 AccessController.doPrivileged(new PrivilegedAction<Object>() {
211 public Object run() {
212 writeMethod.setAccessible(true);
213 return null;
214 }
215 });
216 }
217 else {
218 writeMethod.setAccessible(true);
219 }
220 }
221 final Object value = valueToApply;
222 if (System.getSecurityManager() != null) {
223 try {
224 //將屬性值設定到屬性上去
225 AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
226 public Object run() throws Exception {
227 writeMethod.invoke(object, value);
228 return null;
229 }
230 }, acc);
231 }
232 catch (PrivilegedActionException ex) {
233 throw ex.getException();
234 }
235 }
236 else {
237 writeMethod.invoke(this.object, value);
238 }
239 }
240 catch (TypeMismatchException ex) {
241 throw ex;
242 }
243 catch (InvocationTargetException ex) {
244 PropertyChangeEvent propertyChangeEvent =
245 new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
246 if (ex.getTargetException() instanceof ClassCastException) {
247 throw new TypeMismatchException(propertyChangeEvent, pd.getPropertyType(), ex.getTargetException());
248 }
249 else {
250 throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException());
251 }
252 }
253 catch (Exception ex) {
254 PropertyChangeEvent pce =
255 new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
256 throw new MethodInvocationException(pce, ex);
257 }
258 }
}