好程式設計師Java培訓分享Spring Ioc的原理
今天 好程式設計師 Java 培訓給大家介紹一下關於 SpringIoc 原理的詳解,首先 Ioc 是 InversionofControl 。翻譯過來就是控制反轉,意思是物件之間的關係不再由傳統的程式來控制,而是由 spring 容器來統一控制這些物件建立、協調、銷燬,而物件只需要完成業務邏輯即可。
IoC ( InversionofControl ,控制倒轉)這是 spring 的核心,貫穿始終。所謂 IoC ,對於 spring 框架來說,就是由 spring 來負責控制物件的生命週期和物件間的關係。舉個例子,我們是如何找女朋友的?常見的情況是,我們到處去看哪裡有長得漂亮身材又好的 mm ,然後打聽她們的興趣愛好、 qq 號、電話號…,想辦法認識她們,投其所好送其所好,然後嘿嘿…這個過程是複雜深奧的,我們必須自己設計和麵對每個環節。傳統的程式開發也是如此,在一個物件中,如果要使用另外的物件,就必須得到它(自己 new 一個,或者從 JNDI 中查詢一個),使用完之後還要將物件銷燬(比如 Connection 等),物件始終會和其他的介面或類藕合起來。
IoC 的一個重點是在系統執行中,動態的向某個物件提供它所需要的其他物件。這一點是透過 DI ( DependencyInjection ,依賴注入)來實現的。比如物件 A 需要運算元據庫,以前我們總是要在 A 中自己編寫程式碼來獲得一個 Connection 物件,有了 spring 我們就只需要告訴 spring , A 中需要一個 Connection ,至於這個 Connection 怎麼構造,何時構造, A 不需要知道。在系統執行時, spring 會在適當的時候製造一個 Connection ,然後像打針一樣,注射到 A 當中,這樣就完成了對各個物件之間關係的控制。 A 需要依賴 Connection 才能正常執行,而這個 Connection 是由 spring 注入到 A 中的,依賴注入的名字就這麼來的。那麼 DI 是如何實現的呢? Java1.3 之後一個重要特徵是反射( reflection ),它允許程式在執行的時候動態的生成物件、執行物件的方法、改變物件的屬性, spring 就是透過反射來實現注入的。
下面來讓大家瞭解一下Spring 到底是怎麼執行的
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext(
"applicationContext.xml");
Animal animal = (Animal) context.getBean("animal");
animal.say();
}
這段程式碼你一定很熟悉吧,不過還是讓我們分析一下它吧,首先是applicationContext.xml
<bean id="animal" class="phz.springframework.test.Cat">
<property name="name" value="kitty" />
</bean>
他有一個類phz.springframework.test.Cat
public class Cat implements Animal {
private String name;
public void say() {
System.out.println("I am " + name + "!");
}
public void setName(String name) {
this.name = name;
}
}
實現了phz.springframework.test.Animal 介面
public interface Animal {
public void say();
}
很明顯上面的程式碼輸出Iamkitty! 那麼到底 Spring 是如何做到的呢?接下來就讓我們自己寫個 Spring 來看看 Spring 到底是怎麼執行的吧!首先,我們定義一個 Bean 類,這個類用來存放一個 Bean 擁有的屬性
/* Bean Id */
private String id;
/* Bean Class */
private String type;
/* Bean Property */
private Map<String, Object> properties = new HashMap<String, Object>();
一個Bean 包括 id,type, 和 Properties 。
接下來Spring 就開始載入我們的配置檔案了,將我們配置的資訊儲存在一個 HashMap 中, HashMap 的 key 就是 Bean 的 Id , HasMap 的 value 是這個 Bean ,只有這樣我們才能透過 context.getBean("animal") 這個方法獲得 Animal 這個類。我們都知道 Spirng 可以注入基本型別,而且可以注入像 List , Map 這樣的型別,接下來就讓我們以 Map 為例看看 Spring 是怎麼儲存的吧
Map 配置可以像下面的
<bean id="test">
<property name="testMap">
<map>
<entry key="a">
<value>1</value>
</entry>
<entry key="b">
<value>2</value>
</entry>
</map>
</property>
</bean>
Spring 是怎樣儲存上面的配置呢?,程式碼如下:
(beanProperty.element("map") != null) {
Map<String, Object> propertiesMap = new HashMap<String, Object>();
Element propertiesListMap = (Element) beanProperty
.elements().get(0);
Iterator<?> propertiesIterator = propertiesListMap
.elements().iterator();
while (propertiesIterator.hasNext()) {
Element vet = (Element) propertiesIterator.next();
if (vet.getName().equals("entry")) {
String key = vet.attributeValue("key");
Iterator<?> valuesIterator = vet.elements()
.iterator();
while (valuesIterator.hasNext()) {
Element value = (Element) valuesIterator.next();
if (value.getName().equals("value")) {
propertiesMap.put(key, value.getText());
}
if (value.getName().equals("ref")) {
propertiesMap.put(key, new String[] { value
.attributeValue("bean") });
}
}
}
}
bean.getProperties().put(name, propertiesMap);
}
接下來就進入最核心部分了,讓我們看看Spring 到底是怎麼依賴注入的吧,其實依賴注入的思想也很簡單,它是透過反射機制實現的,在例項化一個類時,它透過反射呼叫類中 set 方法將事先儲存在 HashMap 中的類屬性注入到類中。讓我們看看具體它是怎麼做的吧。首先例項化一個類,像這樣
public static Object newInstance(String className) {
Class<?> cls = null;
Object obj = null;
try {
cls = Class.forName(className);
obj = cls.newInstance();
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
return obj;
}
接著它將這個類的依賴注入進去,像這樣
public static void setProperty(Object obj, String name, String value) {
Class<? extends Object> clazz = obj.getClass();
try {
String methodName = returnSetMthodName(name);
Method[] ms = clazz.getMethods();
for (Method m : ms) {
if (m.getName().equals(methodName)) {
if (m.getParameterTypes().length == 1) {
Class<?> clazzParameterType = m.getParameterTypes()[0];
setFieldValue(clazzParameterType.getName(), value, m,
obj);
break;
}
}
}
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
最後它將這個類的例項返回給我們,我們就可以用了。我們還是以Map 為例看看它是怎麼做的,我寫的程式碼裡面是建立一個 HashMap 並把該 HashMap 注入到需要注入的類中,像這樣:
if (value instanceof Map) {
Iterator<?> entryIterator = ((Map<?, ?>) value).entrySet()
.iterator();
Map<String, Object> map = new HashMap<String, Object>();
while (entryIterator.hasNext()) {
Entry<?, ?> entryMap = (Entry<?, ?>) entryIterator.next();
if (entryMap.getValue() instanceof String[]) {
map.put((String) entryMap.getKey(),
getBean(((String[]) entryMap.getValue())[0]));
}
}
BeanProcesser.setProperty(obj, property, map);
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913864/viewspace-2735467/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 好程式設計師Java乾貨分享Spring框架之IOC原理程式設計師JavaSpring框架
- 好程式設計師Java培訓分享Java程式設計技巧程式設計師Java
- 好程式設計師Java培訓分享SpringBoot -自動配置原理程式設計師JavaSpring Boot
- 好程式設計師Java培訓分享BigDecimal的用法程式設計師JavaDecimal
- 好程式設計師Java培訓分享SpringBoot -YAML程式設計師JavaSpring BootYAML
- 好程式設計師Java培訓分享Java程式設計師技能提升指南程式設計師Java
- 好程式設計師Java培訓分享Java程式設計師常用的工具類庫程式設計師Java
- 好程式設計師Java培訓分享maven-概述程式設計師JavaMaven
- 好程式設計師Java培訓分享註解與反射原理說明程式設計師Java反射
- 好程式設計師Java培訓分享22道Spring Boot面試題!程式設計師JavaSpring Boot面試題
- 好程式設計師Java培訓分享如何快速入門Java程式設計程式設計師Java
- 好程式設計師Java培訓分享20個Java程式設計師基礎題程式設計師Java
- 好程式設計師Java培訓分享Java和HTML的區別?程式設計師JavaHTML
- 好程式設計師Java培訓分享Java之反射技術程式設計師Java反射
- 好程式設計師Java培訓分享如何快速入門Java程式設計師Java
- 好程式設計師Java培訓分享Java包是什麼?程式設計師Java
- 好程式設計師Java培訓分享Java多執行緒程式設計師Java執行緒
- 好程式設計師Java培訓分享Java EE與Java的區別程式設計師Java
- 好程式設計師Java培訓分享本地快取如何設計程式設計師Java快取
- 好程式設計師Java培訓分享SpringBoot -啟動流程程式設計師JavaSpring Boot
- 好程式設計師Java培訓分享For迴圈詳解程式設計師Java
- 好程式設計師Java培訓分享SpringBoot入門篇程式設計師JavaSpring Boot
- 好程式設計師Java培訓分享學Java程式設計要注意什麼程式設計師Java
- 好程式設計師Java培訓分享面試Java的注意事項程式設計師Java面試
- 好程式設計師Java培訓分享Java集合的兩種排序方法程式設計師Java排序
- 好程式設計師Java培訓分享Java物件導向概念解析程式設計師Java物件
- 好程式設計師Java培訓分享Java初學者必讀程式設計師Java
- 好程式設計師Java培訓分享int和Integer的區別程式設計師Java
- 好程式設計師Java培訓分享treeset和hashset的區別程式設計師Java
- 好程式設計師Java培訓分享MySQL算術運算子程式設計師JavaMySql
- 好程式設計師Java培訓分享Mybatis面試題集合程式設計師JavaMyBatis面試題
- 好程式設計師Java培訓分享Java類載入的過程概述程式設計師Java
- 好程式設計師Java培訓分享Java的三大框架怎麼學?程式設計師Java框架
- 好程式設計師Java培訓分享Java面試題集合篇一程式設計師Java面試題
- 好程式設計師Java培訓分享Java面試題集合篇二程式設計師Java面試題
- 好程式設計師Java培訓分享學習Java需要哪些基礎程式設計師Java
- 好程式設計師Java培訓分享Java中級面試題合集程式設計師Java面試題
- 好程式設計師Java培訓分享Java讀寫Properties配置檔案程式設計師Java