什麼是SpringIOC
就是把每一個bean(實體類)與bean(實體類)之間的關係交給第三方容器進行管理。 而不是傳統的在你的對象內部直接控制。
SpringIOC實現原理
- 讀取bean的XML配置文件
- 使用beanId查找bean配置,並獲取配置文件中class地址
- 使用java反射技術實例化對象
- 獲取屬性配置,使用反射技術進行賦值
詳細步驟:
- 1.利用傳入的參數獲取xml文件的流,並且利用dom4j解析成Document對象
- 2.對於Document對象獲取根元素對象後對下面的標籤進行遍歷,判斷是否有符合的id.
- 3.如果找到對應的id,相當於找到了一個Element元素,開始創建對象,先獲取class屬性,根據屬性值利用反射建立對象.
- 4.遍歷標籤下的property標籤,並對屬性賦值.注意,需要單獨處理int,float類型的屬性.因爲在xml配置中這些屬性都是以字符串的形式來配置的,因此需要額外處理.
- 5.如果屬性property標籤有ref屬性,說明某個屬性的值是一個對象,那麼根據id(ref屬性的值)去獲取ref對應的對象,再給屬性賦值.
- 6.返回建立的對象,如果沒有對應的id,或者下沒有子標籤都會返回null
demo
maven
<dependencies> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency> </dependencies>
applicationContext.xml
<beans> <bean id="user1" class="cn.qbz.thread.day1120.User"> <property name="name" value="xiaoMing"></property> <property name="age" value="6"></property> </bean> <bean id="user2" class="cn.qbz.thread.day1120.User"> <property name="name" value="laoWang"></property> <property name="age" value="99"></property> </bean> </beans>
package cn.qbz.thread.day1120; public class User { private String name; private String age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } }
package cn.qbz.thread.day1120; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.lang.reflect.Field; import java.util.List; public class ClassPathXmlApplicationContext { private String xpath; public ClassPathXmlApplicationContext(String xpath) { this.xpath = xpath; } public Object getBean(String beanId) throws Exception { if (isEmpty(beanId)) { throw new Exception("bean Id is null !"); } SAXReader saxReader = new SAXReader(); Document document = saxReader.read(this.getClass().getClassLoader().getResource(xpath)); //獲取到根節點 Element rootElement = document.getRootElement(); //獲取到根節點下的所有的子節點 List<Element> elements = rootElement.elements(); for (Element element : elements) { //獲取到節點上的屬性 String id = element.attributeValue("id"); if (isEmpty(id)) { continue; } if (!id.equals(beanId)) { continue; } // 使用java反射機制初始化對象 String beanClass = element.attributeValue("class"); Class<?> forName = Class.forName(beanClass); Object newInstance = forName.newInstance(); List<Element> propertyElementList = element.elements(); for (Element el : propertyElementList) { String name = el.attributeValue("name"); String value = el.attributeValue("value"); Field declaredField = forName.getDeclaredField(name); declaredField.setAccessible(true); declaredField.set(newInstance, value); } return newInstance; } return null; } public Boolean isEmpty(String str) { return (str == null || "".equals(str.trim())); } }
package cn.qbz.thread.day1120; public class SpringIOCTest { public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext classPath = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) classPath.getBean("user2"); System.out.println(user.getName() + "---" + user.getAge()); } }
注意: this.getClass().getClassLoader().getResourceAsStream(xmlPath) 獲取當前項目路徑xmlPath