日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

ioc spring 上机案例_抛开Spring去理解IOC思想 - 原来IOC容器这么简单

發(fā)布時(shí)間:2024/9/27 javascript 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ioc spring 上机案例_抛开Spring去理解IOC思想 - 原来IOC容器这么简单 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  • 很多小伙伴們看到標(biāo)題可能就會(huì)想到拋開Spring就不會(huì)存在IOC思想了,其實(shí)不然在接下來的文章中就會(huì)講述到。
  • 很多小伙伴在理解IOC的時(shí)候通常會(huì)和Spring放到一起去學(xué)習(xí),首先呢Spring設(shè)計(jì)的非常之巧妙而且里面包含了很多除去IOC的其他功能。這樣會(huì)導(dǎo)致我們?cè)赟pring的基礎(chǔ)去理解IOC就變得很困難。很難抓住其核心思想。
  • 所以本文的標(biāo)題的含義就是單純的去理解IOC思想,然后通過自定義的IOC去加深對(duì)IOC的理解。
  • 看完本文之后再去理解Spring中的IOC其實(shí)思想是一致的,只是實(shí)現(xiàn)上有些出入。畢竟Spring是大神們經(jīng)過深思熟慮后的成果。

傳統(tǒng)的思想(沒有IOC容器的情況下)

在沒有IOC容器的情況下,如果我們需要某個(gè)類具體的操作如下所示:


傳統(tǒng)的Bean創(chuàng)建

  • 程序員對(duì)A進(jìn)行了主動(dòng)的使用(new)即創(chuàng)建了A類,A類中又依賴B類然后在對(duì)B類進(jìn)行創(chuàng)建
  • 創(chuàng)建對(duì)象的權(quán)利現(xiàn)在是程序員手上需要哪個(gè)類就會(huì)對(duì)那個(gè)類進(jìn)行創(chuàng)建
  • B類是由于程序員調(diào)用了A類有對(duì)B類的依賴隨著而創(chuàng)建
  • 總之就是自己動(dòng)手豐衣足食,沒有借助任何中間產(chǎn)物。
  • 優(yōu)點(diǎn)

    • 很直接的一個(gè)優(yōu)點(diǎn)就是簡(jiǎn)單,我們需要什么就去創(chuàng)建什么,在程序員的角度上也是比較直觀容易理解的。

    缺點(diǎn)

    • Bean之間的協(xié)調(diào)關(guān)系是由程序內(nèi)部代碼來控制的即通過New關(guān)鍵字與我們的業(yè)務(wù)代碼進(jìn)行了強(qiáng)耦合。
    • 沒有對(duì)Bean進(jìn)行管理。
    • 對(duì)Bean沒有進(jìn)行統(tǒng)一的管理和配置。

    IOC思想

    首先在這里強(qiáng)調(diào)一下IOC不是Spring提出來了,在Spring之前就已經(jīng)有人提出了IOC思想,只不過在Spring之前都是偏理論化沒有一個(gè)具體的落地方案,Spring在技術(shù)層面把IOC思想體現(xiàn)的淋漓盡致。

    什么是IOC(Inversion of controller)

    • IOC是一種思想,而不是一個(gè)技術(shù)的實(shí)現(xiàn)。
    • 主要的描述是在軟件開發(fā)的領(lǐng)域?qū)ο蟮膭?chuàng)建和管理的問題。
    • 上述我們了解了傳統(tǒng)的開發(fā)模式,我們?cè)趤砜纯慈绻蠭OC的思想下程序員是如何使用對(duì)象的。

    從上圖可知:

    • 程序員只需要告訴IOC自己需要那個(gè)Bean。就不需要關(guān)系該Bean創(chuàng)建的細(xì)節(jié)已經(jīng)該Bean的相關(guān)依賴。這一切IOC容器已經(jīng)幫你做好了。
    • 凡事有得必有失: 這個(gè)過程中我們失去了創(chuàng)建Bean的權(quán)利。
    • 了解了基本的使用后,有人說IOC就是控制反轉(zhuǎn),講到這里你還沒將控制反轉(zhuǎn)?好!別急接下來就是細(xì)講我們常說的控制反轉(zhuǎn)。

    控制反轉(zhuǎn)

    在理解控制反轉(zhuǎn)之前我們首先要清楚控制是指什么? 反轉(zhuǎn)又反轉(zhuǎn)了什么?

    • 控制: 指的就是我們上述說的我們失去的權(quán)利(創(chuàng)建對(duì)象的創(chuàng)建,或者說控制對(duì)象的權(quán)利)
    • 反轉(zhuǎn): 指的是控制權(quán)的轉(zhuǎn)變。在沒有IOC的容器上我們程序員想創(chuàng)建誰就創(chuàng)建誰的權(quán)利。在IOC容器下程序員就只能委屈巴巴的向IOC容器索取對(duì)象。創(chuàng)建對(duì)象的權(quán)利由程序員到IOC容器手里了。

    IOC解決了什么問題?

    • 其實(shí)就是解決了對(duì)象之間的耦合問題。
    • 我們不需要在通過New關(guān)鍵字來創(chuàng)建對(duì)象,而是從容器中獲取達(dá)到一種松耦合的目的。
    • 同時(shí)IOC容器也方便管理容器內(nèi)的所有Bean對(duì)象。所謂的Bean的生命周期。

    IOC和DI的區(qū)別

    將到IOC肯定會(huì)有人想到DI(Dependancy Injection)依賴注入,那這兩者有什么不同和相同呢?

    相同點(diǎn)

    • IOC和DI描述的都是同一件事情(對(duì)象的實(shí)例化以及維護(hù)對(duì)象與對(duì)象已經(jīng)的依賴關(guān)系)

    不同點(diǎn)

    • 首先IOC是一種思想,而DI是一種具體的技術(shù)實(shí)現(xiàn)手段。
    • IOC是站著對(duì)象的角度上對(duì)象的實(shí)例化以及管理從程序員的手里交給了IOC容器
    • DI是站著容器的角度的上會(huì)把對(duì)象的依賴的其他對(duì)象注入到容器中,上述案例中的A類依賴B類IOC容器不僅僅將A類放到容器中還需要將其依賴的B類也一并加載到IOC容器中。

    如何自定義實(shí)現(xiàn)一個(gè)IOC容器

    • 小伙伴們看到這里其實(shí)對(duì)IOC容器已經(jīng)有了一定的了解。那如果在面試的過程中面試官問你如何實(shí)現(xiàn)一個(gè)自定義的IOC容器。你可以講出的具體思路嘛? 可以先想一想在繼續(xù)往下看,看看是不是和自己的想發(fā)不謀而合。
    • 思路大致如下所示:

    • 想必大家都有自己的一定的理解,可能做法比較簡(jiǎn)單,但是對(duì)于理解IOC容器而已其實(shí)已經(jīng)足夠了。如果想更加準(zhǔn)確或者深入了解其底層實(shí)現(xiàn),可以按照這個(gè)思路去看Spring的相關(guān)源碼實(shí)現(xiàn),相信你一定會(huì)得心應(yīng)手。

    小案例

    • 我們通過一個(gè)小案例來寫我們的IOC容器
    • 我們經(jīng)常購(gòu)物,我們可以把購(gòu)物簡(jiǎn)單的理解成下單和減庫存兩個(gè)操作。
    • 有同學(xué)會(huì)問為什么要寫這個(gè)案例啊,不僅為了我們能夠理解IOC容器也為了我們后續(xù)的文章將AOP和AOP的經(jīng)典實(shí)現(xiàn)事務(wù)控制鋪墊的。

    Coding

    • 首先整體的代碼結(jié)構(gòu)很簡(jiǎn)單,在這里也說明一下

    • Bean的配置文件
    <?xml version="1.0" encoding="UTF-8" ?> <!--跟標(biāo)簽beans,里面配置一個(gè)又一個(gè)的bean子標(biāo)簽,每一個(gè)bean子標(biāo)簽都代表一個(gè)類的配置--> <beans><!--id標(biāo)識(shí)對(duì)象,class是類的全限定類名--><bean id="orderDao" class="com.customize.spring.dao.impl.OrderDaoImpl"></bean><bean id="stockDao" class="com.customize.spring.dao.impl.StockDaoImpl"></bean><bean id="orderService" class="com.customize.spring.service.impl.OrderServiceImpl"><!--通過set方法注入--><property name="setOrderDao" ref="orderDao"></property><property name="setStockDao" ref="stockDao"></property></bean> </beans>
    • 創(chuàng)建Bean對(duì)象”工廠“進(jìn)行創(chuàng)建
    • 主要就是讀取xml,通過set方法傳值。
    public class BeanFactory {/*** 存放對(duì)象*/private static Map<String, Object> map = new ConcurrentHashMap<>();/*** 對(duì)外提供的接口* @param id* @return*/public static Object getBean(String id) {return map.get(id);}static {// 只加載一次就是在BeanFactory初始化的時(shí)候去加載類// 任務(wù)一:讀取解析xml,通過反射技術(shù)實(shí)例化對(duì)象并且存儲(chǔ)待用(map集合)System.out.println("開始加載Bean對(duì)象");// 加載xmlInputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");// 解析xmlSAXReader 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);// 處理每個(gè)bean元素,獲取到該元素的id 和 class 屬性String id = element.attributeValue("id");String clazz = element.attributeValue("class");// 通過反射技術(shù)實(shí)例化對(duì)象Class<?> aClass = Class.forName(clazz);Object o = aClass.newInstance();// 存儲(chǔ)到map中待用map.put(id,o);}// 實(shí)例化完成之后維護(hù)對(duì)象的依賴關(guān)系,檢查哪些對(duì)象需要傳值進(jìn)入,根據(jù)它的配置,我們傳入相應(yīng)的值// 有property子元素的bean就有傳值需求List<Element> propertyList = rootElement.selectNodes("//property");// 解析property,獲取父元素for (int i = 0; i < propertyList.size(); i++) {Element element = propertyList.get(i);String name = element.attributeValue("name");String ref = element.attributeValue("ref");// 找到當(dāng)前需要被處理依賴關(guān)系的beanElement parent = element.getParent();// 調(diào)用父元素對(duì)象的反射功能String parentId = parent.attributeValue("id");Object parentObject = map.get(parentId);// 遍歷父對(duì)象中的所有方法,找到"set" + nameMethod[] methods = parentObject.getClass().getMethods();for (int j = 0; j < methods.length; j++) {Method method = methods[j];// 該方法就是 setAccountDao(AccountDao accountDao)if(method.getName().equalsIgnoreCase(name)) {method.invoke(parentObject,map.get(ref));}}// 把處理之后的parentObject重新放到map中map.put(parentId,parentObject);}System.out.println("加載完畢,Map中的Bean對(duì)象個(gè)數(shù)為:" + map.size());} catch (Exception e) {e.printStackTrace();}} }
    • 業(yè)務(wù)代碼
    public class OrderServiceImpl implements OrderService {private OrderDao orderDao;private StockDao stockDao;public void setOrderDao(OrderDao orderDao) {this.orderDao = orderDao;}public void setStockDao(StockDao stockDao) {this.stockDao = stockDao;}@Overridepublic void order(Order order) { // 沒有IOC容器的情況下 // OrderDao orderDao = new OrderDaoImpl(); // // 保存訂單 // orderDao.save(order); // // //扣除庫存 // StockDao stockDao = new StockDaoImpl(); // stockDao.subStock(order.getName());// 有IOC容器的基礎(chǔ)上orderDao.save(order);//扣除庫存stockDao.subStock(order.getName());System.out.println("下單成功");} }
    • 啟動(dòng)

    • 測(cè)試
      • 地址: http://localhost:9080/order?userId=857&name=ipone
      • 配圖:

    項(xiàng)目地址

    • 項(xiàng)目地址
    • 有幫忙到你記得點(diǎn)個(gè)小星星哦。

    總結(jié)

    • 本人水平有限有什么不正確的地方,歡迎大家留言區(qū)討論。

    總結(jié)

    以上是生活随笔為你收集整理的ioc spring 上机案例_抛开Spring去理解IOC思想 - 原来IOC容器这么简单的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。