1. 程式人生 > >Spring IOC原理原始碼解析

Spring IOC原理原始碼解析

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

相關推薦

Spring IOC原理原始碼解析(@Autowired原理詳解 :標識屬性與方法)(二 )

原始碼推薦看這篇部落格的時候開啟Spring原始碼,一邊看原始碼,一邊看部落格上程式碼的關鍵處的註釋,這樣能更好的理解Spring IOC的流程及內部實現和使用方法。如果你對IOC的原理有些瞭解,則這些註釋能幫你更深入的理解其實現方式。 Spring容器在每個

Spring IOC原理原始碼解析(@Autowired原理詳解 :標識建構函式)(一 )

IOC,inversion of control 控制反轉,有時候也叫DI,dependency injection 依賴注入,是一種程式碼解耦的方式。 在一個類中定義一個屬性,正常情況下需要在此類中有對此屬性賦值的程式碼,如setter方法,或者在建構函式中

Spring IOC原理原始碼解析

1 //實現屬性依賴注入功能 2 private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException { 3 //PropertyTokenHold

Spring IOC 原理深層解析

## 1 Spring IOC概念認識 ### 1.1 區別IOC與DI 首先我們要知道IOC(Inverse of Control:控制反轉)是一種設計思想,就是 **將原本在程式中手動建立物件的控制權,交由Spring框架來管理。**這並非Spring特有,在其他語言裡面也有體現。IOC容器是Spri

Spring原始碼解讀Spring IOC原理

1 //實現屬性依賴注入功能 2 private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException { 3 //PropertyTokenHo

(精)Spring IOC核心原始碼學習III:bean標籤和自定義標籤實現原理

本文將解析spring bean定義標籤和自定義標籤的解析實現原理。這裡說的標籤僅限於以xml作為bean定義描述符的spring容器,繼承AbstractXmlApplicationContext的一些子 容器,如XmlApplicationContext、ClassPat

Spring IOCSpring原始碼解讀Spring IOC原理

一、什麼是Ioc/DI?     IoC 容器:最主要是完成了完成物件的建立和依賴的管理注入等等。 先從我們自己設計這樣一個視角來考慮: 所謂控制反轉,就是把原先我們程式碼裡面需要實現的物件建立、依賴的程式碼,反轉給容器來幫忙實現。那麼必然的我們需要建立一個容器

spring 原始碼解讀Spring IOC原理

//建立Bean的例項物件 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { //檢查確認Bean是可例項化的 Cl

Spring實戰】Spring註解配置工作原理原始碼解析

一、背景知識在【Spring實戰】Spring容器初始化完成後執行初始化資料方法一文中說要分析其實現原理,於是就從原始碼中尋找答案,看原始碼容易跑偏,因此應當有個主線,或者帶著問題、目標去看,這樣才能最大限度的提升自身程式碼水平。由於上文中大部分都基於註解進行設定的(Spri

SpringIOC原始碼解析(二)

在《Spring的IOC的原始碼解析(一)》中完成了BeanDefinition的解析和載入,下邊會接著分析bean的PostProcessor一、準備一些公共的物件邏輯都在這句程式碼中:prepareBeanFactory(beanFactory);主要操作有:設定類載入器

SpringIOC原始碼解析(三)

在《Spring的IOC的原始碼解析(二)》中完成了BFPP和BPP的處理分析;這篇接著分bean的例項化。在用bean工廠建立bean物件時,呼叫的是父類AbstractBeanFactory中提供的getBean的系列方法。往下,在AbstractAutowireCapa

Spring Boot中@ConfigurationProperties註解實現原理原始碼解析

0. 開源專案推薦 Pepper Metrics是我與同事開發的一個開源工具(https://github.com/zrbcool/pepper-metrics),其通過收集jedis/mybatis/httpservlet/dubbo/motan的執行效能統計,並暴露成prometheus等主流時序資料庫相

Spring Ioc原理

service 新的 cto str gets ice instance brush users IOC實現原理:1 配置xml文件 2 dom4j根據xml文件得到id對應的classvalue 3反射創建類對象 4創建一個新的實例,返回實例 //IOC原理 // p

轉載 JAVA spring ioc原理 原文地址:http://blog.csdn.net/it_man/article/details/4402245

nbsp animal 很難 details 如何實現 拋出異常 感覺 註入 extend 最近,買了本Spring入門書:spring In Action 。大致瀏覽了下感覺還不錯。就是入門了點。Manning的書還是不錯的,我雖然不像哪些只看Manning書的人那樣專註

深入研究Spring-IoC原始碼分析依賴注入

1.前言 對於容器建立的過程已經闡述過一遍了,下面是依賴注入的問題。Spring提供的依賴注入的方法主要由兩種:一種是通過getBean的方法;另一種是通過註解@Autowaire。 需要指出的是依賴注入的過程是使用者第一次向ioc容器索要Bean的時候開始生產的,也可以通過設定

深入研究Spring-IoC原始碼分析容器建立

1.前言 從之前的分析中可以知道IOC容器的建立大致分為3步:Resource定位、BeanDefinition載入解析、向容器註冊BeanDefinition。 Tiny-spring手動實現了Spring框架,通過對這個原始碼的解讀可以更好更有效的理解Spring。 2.

Spring---IOC原理 SpringIOC原理[通俗解釋一下]

Spring的IOC原理(轉載) 在網上看到一篇文章,感覺寫得挺不錯的,轉載一下,本文轉載自:http://blog.csdn.net/m13666368773/article/details/7802126 Spring的IOC原理[通俗解釋

Spring Cloud Config原始碼解析(一)

   這是第一次寫原始碼的解析,主要是給自己留一個印象,有很多不充足的地方以後自己慢慢補充。這個spring cloud config原始碼的解析是以2.1.0.BUILD-SNAPSHOT為基礎,時間是2018-10-05以前的程式碼來分析。spring cloud config主要有3

spring ioc原理 spring ioc原理(看完後大家可以自己寫一個spring

原 spring ioc原理(看完後大家可以自己寫一個spring) 2009年08月02日 20:33:00 超級谷歌 閱讀數:332663

Spring AOP 原理原始碼深度剖析

轉載請標明出處:https://www.fangzhipeng.com 本文轉載於吉姆餐廳ak   概述 AOP(Aspect-Oriented Programming) 面向切面程式設計。Spring Aop 在 Spring框架中的地位舉足輕重,主要用於實現事務、快取、安全等功