編碼剖析Spring管理Bean的原理
阿新 • • 發佈:2018-06-06
bean對象 控制 eva BE 並且 return select lec exception
在Spring的第一個案例中,我們已經知道了怎麽將bean交給Spring容器進行管理,並且明白了怎麽從Spring容器中獲取bean。那我們就有一個疑問了:Spring是如何創建並管理bean的呢?現在我們就來編碼剖析Spring管理Bean的原理。
本文是在Spring的第一個案例的基礎上展開的。
我們要使用dom4j讀取Sping的配置文件——beans.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.xsd"> <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean> </beans>
那麽就需要將dom4j所需的jar包導入該項目中。dom4j所需的jar包為:
- dom4j-1.6.1.jar
- jaxen-1.1-beta-6.jar
dom4j讀取到諸如
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean>
這樣的內容時,務必需要將讀取到的bean的信息存到一個JavaBean對象中。於是我們可在junit.test包下創建這樣一個JavaBean——BeanDefinition.java,其代碼為:
/** * 將讀取到的bean的信息存到一個JavaBean對象中 * */ public class BeanDefinition {private String id; private String className; public BeanDefinition(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; } }
接下來我們就創建一個傳智播客版的Spring容器來模擬Spring容器。在junit.test下新建一個類——ItcastClassPathXMLApplicationContext.java,其代碼如下:
/** * 傳智播客版Spring容器 * */ public class ItcastClassPathXMLApplicationContext { private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>(); private Map<String, Object> sigletons = new HashMap<String, Object>(); public ItcastClassPathXMLApplicationContext(String filename) { this.readXML(filename); this.instanceBeans(); } /** * 完成bean的實例化 */ private void instanceBeans() { for (BeanDefinition beanDefinition : beanDefines) { try { if (beanDefinition.getClassName() != null && !"".equals(beanDefinition.getClassName().trim())) { sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance()); } } catch (Exception e) { e.printStackTrace(); } } } /** * 讀取XML配置文件 * @param filename */ private void readXML(String filename) { SAXReader saxReader = new SAXReader(); Document document = null; try { URL xmlpath = this.getClass().getClassLoader().getResource(filename); document = saxReader.read(xmlpath); Map<String, String> nsMap = new HashMap<String, String>(); nsMap.put("ns", "http://www.springframework.org/schema/beans"); // 加入命名空間 XPath xsub = document.createXPath("//ns:beans/ns:bean"); // 創建beans/bean查詢路徑 xsub.setNamespaceURIs(nsMap); // 設置命名空間 List<Element> beans = xsub.selectNodes(document); // 獲取文檔下所有bean節點 for (Element element : beans) { String id = element.attributeValue("id"); // 獲取id屬性值 String clazz = element.attributeValue("class"); // 獲取class屬性值 BeanDefinition beanDefine = new BeanDefinition(id, clazz); beanDefines.add(beanDefine); } } catch (Exception e) { e.printStackTrace(); } } /** * 獲取bean實例 * @param beanName * @return */ public Object getBean(String beanName) { return this.sigletons.get(beanName); } }
這樣,傳智播客版的Spring容器就創建出來了。接下來我們就要測試傳智播客版的Spring容器是否能夠取得bean實例,只須修改SpringTest類的代碼為:
public class SpringTest { @Test public void test() { // ApplicationContext是接口 // ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); // 實例化Spring容器 // PersonService personService = (PersonService) ctx.getBean("personService"); // 從Spring容器取得bean // personService.save(); ItcastClassPathXMLApplicationContext ctx = new ItcastClassPathXMLApplicationContext("beans.xml"); // 實例化Spring容器 PersonService personService = (PersonService) ctx.getBean("personService"); // 從Spring容器取得bean personService.save(); } }
測試test()方法,Eclipse控制臺打印如下:
通過編寫代碼剖析Spring管理Bean的原理,我們就能深刻理解Spring內部到底是如何創建並管理bean實例的.
編碼剖析Spring管理Bean的原理