1.IOC原理模擬
Spring兩大核心功能,IOC(Inverse of Control) 和 AOP(Aspect-Oriented-Programming)
IOC原理模擬:
有這樣一個beans.xml:
1 <beans> 2 <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl" /> 3 <bean id="userService" class="com.bjsxt.service.UserService" > 4 <property name="userDAO" ref="u"/> 5</bean> 6 7 </beans>
現在我們想讀取這個配置文件,實例化裏面所有的bean,將其放到我們的容器中
1. 首先我們的容器是一個 Map,裏面存放我們bean的實力對象
private Map<String,Object> beans = new HashMap<String,Object>();
2.開始解析這個配置文件
a)讀取這個配置文件,先獲取這個配置文件的根節點,再獲取根節點下所有標簽名為 <bean> 的節點
1 Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml")); //構造文檔對象 2 Element root = doc.getRootElement(); //獲取根元素 3 List list = root.getChildren("bean"); //獲得根節點下所有標簽名為 bean 的節點
b)遍歷所有的<bean>節點,拿到裏面的 id 屬性和 class屬性
for(int i=0;i<list.size();i++) { Element element=(Element)list.get(i); String id=element.getAttributeValue("id"); String clazz=element.getAttributeValue("class");
c)根據每個bean中的class屬性的值,創建這個類的一個實例,將這個實例對象作為 value,bean中的id屬性作為 key ,put進我們的容器中
Object o = Class.forName(clazz).newInstance(); beans.put(id, o); //key 為 id 屬性,value為 class 屬性的實例
d)遍歷所有的<bean>節點,判斷 <bean> 節點後面是否還有 <property>節點
如果有的話,說明 這個bean中還需要註入其他實例對象 作為 屬性 註入給它,所以我們需要繼續去讀這個 <property>,拿到 <property> 的 name 屬性 和 ref屬性
for(Element propertyElement : (List<Element>)element.getChildren("property")) { //如果某個bean中,存在property,即 存在 set***方法,則將xml文件指定的class註入進行 String name = propertyElement.getAttributeValue("name"); //userDAO String ref= propertyElement.getAttributeValue("ref"); //u
e)ref關聯的是 某個 bean的id,所以通過ref屬性,就可以 get 出 對應的實例對象,用於註入
Object beanObject = beans.get(ref); //UserDAOImpl instance
f)既然某個bean 希望 有 另外一個bean 可以註入進來,那麽肯定要有對應 set方法,這個時候就需要用到 name 屬性
通過name屬性,得到 註入的位置,如這裏 name屬性的值是 userDAO,說明該bean 需要一個UserDAO 類型的屬性
通過字符串拼接得到 setUserDAO方法,
String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1); //拼接成setUserDAO
g)反射調用該方法,完成 bean 的註入
Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]); //反射調用 setUserDAO 方法,將userDao 註入 到 userService中 m.invoke(o, beanObject);
h)外界調用
當程序一啟動,就啟動我們的容器,讀取配置文件,完成bean 初始化和 註入,放到我們容器中
UserService service = (UserService) applicationContext.getBean("userService");
getBean方法,實際上就是 調用我們 容器(Map)的 get方法,通過 bean節點的id屬性,拿到對象bean的實例
1.IOC原理模擬