Spring容器預設情況下,當服務啟動時,解析設定檔,執行個體化檔案中的所有類。
我們直接使用spring時,擷取spring注入的bean是這樣的,
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
MyService myService1 = (MyService) ctx.getBean("myService");
那下面我們類比spring管理bean這個的過程,代碼如下
1. 第一步,建立java project,引入spring.jar
2. 建立spring.xml設定檔
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
</beans>
3. 建立介面MyService,只需要一個測試方法save
4. 建立實作類別MyServiceImpl,控制台輸出一句話
5. 建立一個自己的解析類MyClassPathXmlApplicationContext
主要是構造方法中的兩步
// 裝載執行個體化bean
private Map<String, Object> beanMap =
new HashMap<String, Object>();
// 裝載設定檔的屬性和值
private List<MyBeans> beanlist =
new ArrayList<MyBeans>();
public MyClassPathXmlApplicationContext(String filename) {
//第一步,解析spring設定檔
readXml(filename);
//第二步,通過反射,執行個體化所有注入bean
initBeans();
}
/**
* 通過反射機制,初始化設定檔中的bean
*/
private void initBeans() {
for (MyBeans bean : beanlist) {
try {
if (bean.getClassName() !=
null && !"".equals(bean.getClassName())) {
beanMap.put(bean.getId(), Class.forName(bean.getClassName()).newInstance());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 解析設定檔,把解析後的bean設定到實體中,並保持到list
*
* @param filename
*/
private void readXml(String filename) {
SAXReader reader = new SAXReader();
Document doc = null;
URL xmlpath = this.getClass().getClassLoader().getResource(filename);
try {
Map<String, String> nsMap = new HashMap<String, String>();
nsMap.put("ns", "http://www.springframework.org/schema/beans");
doc = reader.read(xmlpath);
XPath xpath = doc.createXPath("//ns:beans//ns:bean");// 建立//ns:beans//ns:bean查詢路徑
xpath.setNamespaceURIs(nsMap);// 設定命名空間
List<Element> eles = xpath.selectNodes(doc);// 取得文檔下所有節點
for (Element element : eles) {
String id = element.attributeValue("id");
String cn = element.attributeValue("class");
//自訂實體bean,儲存設定檔中id和class
MyBeans beans = new MyBeans(id, cn);
beanlist.add(beans);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public Object getBean(String beanId) {
return beanMap.get(beanId);
}
6. 實體類
package com.mooing.service;
public class MyBeans {
private String id;
private String className;
public MyBeans(String id, String className) {
this.id = id;
this.className = className;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}
7. 測試
MyClassPathXmlApplicationContext ctx = new MyClassPathXmlApplicationContext("spring.xml");
MyService myService = (MyService) ctx.getBean("myService");
myService.save();
總結:
自訂代碼同樣可以得到使用spring容器執行個體化的效果,也就是說,實際spring執行個體化管理bean時,也是經過兩大步:第一,服務啟動解析設定檔,並儲存設定檔中的元素;第二,執行個體化所有元素,並提供擷取執行個體方法。