最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

五分鐘手?jǐn)]一個(gè)Spring容器(萌芽版)

 更新時(shí)間:2022年03月07日 15:11:42   作者:三分惡  
Spring的兩大內(nèi)核分別是IOC和AOP,其中最最核心的是IOC。這篇文章主要介紹了五分鐘,手?jǐn)]一個(gè)Spring容器的相關(guān)知識(shí),需要的朋友可以參考下

大家好,我是老三,Spring是我們最常用的開(kāi)源框架,經(jīng)過(guò)多年發(fā)展,Spring已經(jīng)發(fā)展成枝繁葉茂的大樹(shù),讓我們難以窺其全貌。

這節(jié),我們回歸Spring的本質(zhì),五分鐘手?jǐn)]一個(gè)Spring容器,揭開(kāi)Spring神秘的面紗!

從什么是IOC開(kāi)始?

Spring——春天,Java編程世界的春天是由一位音樂(lè)家——Rod Johnson帶來(lái)的。

Rod Johnson先后編寫(xiě)了兩本巨著《Expert One-on-One J2EE Design and Development》、《Expert One-on-One J2EE Development without EJB》,拉起了挑戰(zhàn)正統(tǒng)Java EE框架EJB的大旗。

Rod Johnson不僅是一名旗手,更是開(kāi)發(fā)了Spring這一輕量級(jí)框架,像一名勇敢的龍騎兵一樣,對(duì)EJB發(fā)動(dòng)了沖鋒,并最終戰(zhàn)勝了EJB,讓Spring成為Java EE事實(shí)上的標(biāo)準(zhǔn)。

Spring的兩大內(nèi)核分別是IOC和AOP,其中最最核心的是IOC。

所謂的IOC(控制反轉(zhuǎn)):就是由容器來(lái)負(fù)責(zé)控制對(duì)象的生命周期和對(duì)象間的關(guān)系。以前是我們想要什么,就自己創(chuàng)建什么,現(xiàn)在是我們需要什么,容器就給我們送來(lái)什么。

也就是說(shuō),控制對(duì)象生命周期的不再是引用它的對(duì)象,而是容器。對(duì)具體對(duì)象,以前是它控制其它對(duì)象,現(xiàn)在所有對(duì)象都被容器控制,所以這就叫控制反轉(zhuǎn)

也許你還聽(tīng)到另外一個(gè)概念DI(依賴注入),它指的是容器在實(shí)例化對(duì)象的時(shí)候把它依賴的類注入給它,我們也可以認(rèn)為,DI是IOC的補(bǔ)充和實(shí)現(xiàn)。

工廠和Spring容器

Spring是一個(gè)成熟的框架,為了滿足擴(kuò)展性、實(shí)現(xiàn)各種功能,所以它的實(shí)現(xiàn)如同枝節(jié)交錯(cuò)的大樹(shù)一樣,現(xiàn)在讓我們把視線從Spring本身移開(kāi),來(lái)看看一個(gè)萌芽版的Spring容器怎么實(shí)現(xiàn)。

Spring的IOC本質(zhì)就是一個(gè)大工廠,我們想想一個(gè)工廠是怎么運(yùn)行的呢?

  • 生產(chǎn)產(chǎn)品:一個(gè)工廠最核心的功能就是生產(chǎn)產(chǎn)品。在Spring里,不用Bean自己來(lái)實(shí)例化,而是交給Spring,應(yīng)該怎么實(shí)現(xiàn)呢?——答案毫無(wú)疑問(wèn),反射

那么這個(gè)廠子的生產(chǎn)管理是怎么做的?你應(yīng)該也知道——工廠模式

  • 庫(kù)存產(chǎn)品:工廠一般都是有庫(kù)房的,用來(lái)庫(kù)存產(chǎn)品,畢竟生產(chǎn)的產(chǎn)品不能立馬就拉走。Spring我們都知道是一個(gè)容器,這個(gè)容器里存的就是對(duì)象,不能每次來(lái)取對(duì)象,都得現(xiàn)場(chǎng)來(lái)反射創(chuàng)建對(duì)象,得把創(chuàng)建出的對(duì)象存起來(lái)。
  • 訂單處理:還有最重要的一點(diǎn),工廠根據(jù)什么來(lái)提供產(chǎn)品呢?訂單。這些訂單可能五花八門,有線上簽簽的、有到工廠簽的、還有工廠銷售上門簽的……最后經(jīng)過(guò)處理,指導(dǎo)工廠的出貨。

在Spring里,也有這樣的訂單,它就是我們bean的定義和依賴關(guān)系,可以是xml形式,也可以是我們最熟悉的注解形式。

那對(duì)應(yīng)我們的萌芽版的Spring容器是什么樣的呢?

訂單:Bean定義

Bean可以通過(guò)一個(gè)配置文件定義,我們會(huì)把它解析成一個(gè)類型。

beans.properties

為了偷懶,這里直接用了最方便解析的properties,用一個(gè)<key,value>類型的配置來(lái)代表Bean的定義,其中key是beanName,value是class

userDao:cn.fighter3.bean.UserDao

BeanDefinition.java

bean定義類,配置文件中bean定義對(duì)應(yīng)的實(shí)體

public class BeanDefinition {
    private String beanName;
    private Class beanClass;
     //省略getter、setter  
 }   

獲取訂單:資源加載

接下訂單之后,就要由銷售向生產(chǎn)部門交接,讓生產(chǎn)部門知道商品的規(guī)格、數(shù)量之類。

資源加載器,就是來(lái)完成這個(gè)工作的,由它來(lái)完成配置文件中配置的加載。

public class ResourceLoader {

    public static Map<String, BeanDefinition> getResource() {
        Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>(16);
        Properties properties = new Properties();
        try {
            InputStream inputStream = ResourceLoader.class.getResourceAsStream("/beans.properties");
            properties.load(inputStream);
            Iterator<String> it = properties.stringPropertyNames().iterator();
            while (it.hasNext()) {
                String key = it.next();
                String className = properties.getProperty(key);
                BeanDefinition beanDefinition = new BeanDefinition();
                beanDefinition.setBeanName(key);
                Class clazz = Class.forName(className);
                beanDefinition.setBeanClass(clazz);
                beanDefinitionMap.put(key, beanDefinition);
            }
            inputStream.close();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return beanDefinitionMap;
    }

}

訂單分配:Bean注冊(cè)

對(duì)象注冊(cè)器,這里用于單例bean的緩存,我們大幅簡(jiǎn)化,默認(rèn)所有bean都是單例的??梢钥吹剿^單例注冊(cè),也很簡(jiǎn)單,不過(guò)是往HashMap里存對(duì)象。

public class BeanRegister {

    //單例Bean緩存
    private Map<String, Object> singletonMap = new HashMap<>(32);
    /**
     * 獲取單例Bean
     *
     * @param beanName bean名稱
     * @return
     */
    public Object getSingletonBean(String beanName) {
        return singletonMap.get(beanName);
    }
     * 注冊(cè)單例bean
     * @param beanName
     * @param bean
    public void registerSingletonBean(String beanName, Object bean) {
        if (singletonMap.containsKey(beanName)) {
            return;
        }
        singletonMap.put(beanName, bean);
}

生產(chǎn)車間:對(duì)象工廠

好了,到了我們最關(guān)鍵的生產(chǎn)部門了,在工廠里,生產(chǎn)產(chǎn)品的是車間,在IOC容器里,生產(chǎn)對(duì)象的是BeanFactory。

  • 對(duì)象工廠,我們最核心的一個(gè)類,在它初始化的時(shí)候,創(chuàng)建了bean注冊(cè)器,完成了資源的加載。
  • 獲取bean的時(shí)候,先從單例緩存中取,如果沒(méi)有取到,就創(chuàng)建并注冊(cè)一個(gè)bean
public class BeanFactory {

    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

    private BeanRegister beanRegister;

    public BeanFactory() {
        //創(chuàng)建bean注冊(cè)器
        beanRegister = new BeanRegister();
        //加載資源
        this.beanDefinitionMap = new ResourceLoader().getResource();
    }

    /**
     * 獲取bean
     *
     * @param beanName bean名稱
     * @return
     */
    public Object getBean(String beanName) {
        //從bean緩存中取
        Object bean = beanRegister.getSingletonBean(beanName);
        if (bean != null) {
            return bean;
        }
        //根據(jù)bean定義,創(chuàng)建bean
        return createBean(beanDefinitionMap.get(beanName));
    }

    /**
     * 創(chuàng)建Bean
     *
     * @param beanDefinition bean定義
     * @return
     */
    private Object createBean(BeanDefinition beanDefinition) {
        try {
            Object bean = beanDefinition.getBeanClass().newInstance();
            //緩存bean
            beanRegister.registerSingletonBean(beanDefinition.getBeanName(), bean);
            return bean;
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }
}

生產(chǎn)銷售:測(cè)試

UserDao.java

我們的Bean類,很簡(jiǎn)單

public class UserDao {

    public void queryUserInfo(){
        System.out.println("A good man.");
    }
}

單元測(cè)試

public class ApiTest {
    @Test
    public void test_BeanFactory() {
        //1.創(chuàng)建bean工廠(同時(shí)完成了加載資源、創(chuàng)建注冊(cè)單例bean注冊(cè)器的操作)
        BeanFactory beanFactory = new BeanFactory();

        //2.第一次獲取bean(通過(guò)反射創(chuàng)建bean,緩存bean)
        UserDao userDao1 = (UserDao) beanFactory.getBean("userDao");
        userDao1.queryUserInfo();

        //3.第二次獲取bean(從緩存中獲取bean)
        UserDao userDao2 = (UserDao) beanFactory.getBean("userDao");
        userDao2.queryUserInfo();
    }
}

運(yùn)行結(jié)果

A good man.
A good man.

至此,我們一個(gè)萌芽版的Spring容器就完成了。

考慮一下,它有哪些不足呢?是否還可以抽象、擴(kuò)展、解耦……

細(xì)細(xì)想想這些東西,你是不是對(duì)真正的Spring IOC容器為何如此復(fù)雜,有所理解了呢?

參考:

[1]. 《Spring揭秘》

[2].小傅哥 《手?jǐn)]Spring》

[3].《精通Spring4.X企業(yè)應(yīng)用開(kāi)發(fā)實(shí)戰(zhàn)》

到此這篇關(guān)于五分鐘,手?jǐn)]一個(gè)Spring容器的文章就介紹到這了,更多相關(guān)Spring容器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java基礎(chǔ)之?dāng)?shù)組常用操作總結(jié)(必看篇)

    java基礎(chǔ)之?dāng)?shù)組常用操作總結(jié)(必看篇)

    下面小編就為大家?guī)?lái)一篇java基礎(chǔ)之?dāng)?shù)組常用操作總結(jié)(必看篇)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • Java之Runnable啟動(dòng)線程的使用方式

    Java之Runnable啟動(dòng)線程的使用方式

    這篇文章主要介紹了Java之Runnable啟動(dòng)線程的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • RocketMQ的消費(fèi)者類型與最佳實(shí)踐詳解

    RocketMQ的消費(fèi)者類型與最佳實(shí)踐詳解

    這篇文章主要介紹了RocketMQ的消費(fèi)者類型與最佳實(shí)踐詳解,在?RocketMQ?5.0?中,更加強(qiáng)調(diào)了客戶端類型的概念,尤其是消費(fèi)者類型,為了滿足多樣的?RocketMQ?中一共有三種不同的消費(fèi)者類型,分別是?PushConsumer、SimpleConsumer?和?PullConsumer,需要的朋友可以參考下
    2023-10-10
  • 必須詳細(xì)與全面的Java開(kāi)發(fā)環(huán)境搭建圖文教程

    必須詳細(xì)與全面的Java開(kāi)發(fā)環(huán)境搭建圖文教程

    本篇文章內(nèi)容包括:Linux理論與實(shí)操,MySQL實(shí)操,JDK實(shí)操,Tomcat實(shí)操和Tomcat實(shí)操,需要的朋友可以參考下
    2019-11-11
  • 淺談Zookeeper開(kāi)源客戶端框架Curator

    淺談Zookeeper開(kāi)源客戶端框架Curator

    這篇文章主要介紹了淺談Zookeeper開(kāi)源客戶端框架Curator的相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-10-10
  • springboot中PostMapping正常接收json參數(shù)后返回404問(wèn)題

    springboot中PostMapping正常接收json參數(shù)后返回404問(wèn)題

    這篇文章主要介紹了springboot中PostMapping正常接收json參數(shù)后返回404問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • SpringBoot使用JPA實(shí)現(xiàn)查詢部分字段

    SpringBoot使用JPA實(shí)現(xiàn)查詢部分字段

    這篇文章主要介紹了SpringBoot使用JPA實(shí)現(xiàn)查詢部分字段方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java后端實(shí)現(xiàn)生成驗(yàn)證碼圖片的示例代碼

    Java后端實(shí)現(xiàn)生成驗(yàn)證碼圖片的示例代碼

    驗(yàn)證碼是一種用于驗(yàn)證用戶身份或確保用戶操作安全的技術(shù)手段,通常以圖形、聲音或文字的形式出現(xiàn),本文主要介紹了如何通過(guò)java實(shí)現(xiàn)生成驗(yàn)證碼圖片,需要的可以參考下
    2023-12-12
  • Java中Map的entrySet()使用說(shuō)明

    Java中Map的entrySet()使用說(shuō)明

    這篇文章主要介紹了Java中Map的entrySet()使用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • Java安全之Mojarra?JSF反序列化講解

    Java安全之Mojarra?JSF反序列化講解

    JSF?和類似的?Web?技術(shù)之間的區(qū)別在于?JSF?使用?ViewStates(除了會(huì)話)來(lái)存儲(chǔ)視圖的當(dāng)前狀態(tài)(例如,當(dāng)前應(yīng)該顯示視圖的哪些部分),這篇文章主要介紹了Java安全之Mojarra?JSF反序列化知識(shí)講解,包括漏洞復(fù)現(xiàn)和漏洞分析,需要的朋友可以參考下
    2022-11-11

最新評(píng)論

桃园市| 沽源县| 揭阳市| 红安县| 西青区| 土默特左旗| 理塘县| 汉寿县| 讷河市| 景东| 闵行区| 新乐市| 综艺| 改则县| 株洲县| 翼城县| 措勤县| 云和县| 长顺县| 青冈县| 铜川市| 佛冈县| 青浦区| 双桥区| 东明县| 兴安盟| 商城县| 临城县| 新密市| 永德县| 湖口县| 安福县| 盐边县| 印江| 建水县| 乐亭县| 南汇区| 南丰县| 楚雄市| 拜城县| 沂南县|