spring源碼——模擬實現ioc和aop

模擬實現spring的ioc和aop


/**
 * 工廠類,生產對象(使用反射技術)
 */
public class BeanFactory {

    /**
     * 任務一:讀取解析xml,通過反射技術實例化對象並且存儲待用(map集合)
     * 任務二:對外提供獲取實例對象的接口(根據id獲取)
     */

    private static Map<String,Object> singletonObjects = new HashMap<>();  // 存儲對象


    /**
     * 解析xml
     */
    public  void parseXml(){

        // 任務一:讀取解析xml,通過反射技術實例化對象並且存儲待用(map集合)
        // 加載xml
        InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
        // 解析xml
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();
            List<Element> beanList = rootElement.selectNodes("//bean");
            for (int i = 0; i < beanList.size(); i++) {
                Element element =  beanList.get(i);
                // 處理每個bean元素,獲取到該元素的id 和 class 屬性
                String id = element.attributeValue("id");        // accountDao
                String clazz = element.attributeValue("class");  // com.lagou.edu.dao.impl.JdbcAccountDaoImpl
                // 通過反射技術實例化對象
                Class<?> aClass = Class.forName(clazz);
                Object o = aClass.newInstance();  // 實例化之後的對象

                // 存儲到map中待用
                singletonObjects.put(id,o);

            }

            // 實例化完成之後維護對象的依賴關係,檢查哪些對象需要傳值進入,根據它的配置,我們傳入相應的值
            // 有property子元素的bean就有傳值需求
            List<Element> propertyList = rootElement.selectNodes("//property");
            // 解析property,獲取父元素
            for (int i = 0; i < propertyList.size(); i++) {
                Element element =  propertyList.get(i);   //<property name="AccountDao" ref="accountDao"></property>
                String name = element.attributeValue("name");
                String ref = element.attributeValue("ref");

                // 找到當前需要被處理依賴關係的bean
                Element parent = element.getParent();

                // 調用父元素對象的反射功能
                String parentId = parent.attributeValue("id");
                Object parentObject = singletonObjects.get(parentId);
                // 遍歷父對象中的所有方法,找到"set" + name
                Method[] methods = parentObject.getClass().getMethods();
                for (int j = 0; j < methods.length; j++) {
                    Method method = methods[j];
                    if(method.getName().equalsIgnoreCase("set" + name)) {  // 該方法就是 setAccountDao(AccountDao accountDao)
                        method.invoke(parentObject,singletonObjects.get(ref));
                    }
                }

                // 把處理之後的parentObject重新放到map中
                singletonObjects.put(parentId,parentObject);

            }

        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    // 任務二:對外提供獲取實例對象的接口(根據id獲取)
    public static  Object getBean(String id) {
        return singletonObjects.get(id);
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章