91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何實現一個萌芽版的Spring容器

發布時間:2022-03-06 18:38:18 來源:億速云 閱讀:187 作者:小新 欄目:開發技術

這篇文章主要為大家展示了“如何實現一個萌芽版的Spring容器”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“如何實現一個萌芽版的Spring容器”這篇文章吧。

從什么是IOC開始?

Spring--春天,Java編程世界的春天是由一位音樂家--Rod Johnson帶來的。

Rod Johnson先后編寫了兩本巨著《Expert One-on-One J2EE Design and Development》、《Expert One-on-One J2EE Development without EJB》,拉起了挑戰正統Java EE框架EJB的大旗。

如何實現一個萌芽版的Spring容器

Rod Johnson不僅是一名旗手,更是開發了Spring這一輕量級框架,像一名勇敢的龍騎兵一樣,對EJB發動了沖鋒,并最終戰勝了EJB,讓Spring成為Java EE事實上的標準。

如何實現一個萌芽版的Spring容器

Spring的兩大內核分別是IOC和AOP,其中最最核心的是IOC。

所謂的IOC(控制反轉):就是由容器來負責控制對象的生命周期和對象間的關系。以前是我們想要什么,就自己創建什么,現在是我們需要什么,容器就給我們送來什么。

如何實現一個萌芽版的Spring容器

也就是說,控制對象生命周期的不再是引用它的對象,而是容器。對具體對象,以前是它控制其它對象,現在所有對象都被容器控制,所以這就叫控制反轉。

如何實現一個萌芽版的Spring容器

也許你還聽到另外一個概念DI(依賴注入),它指的是容器在實例化對象的時候把它依賴的類注入給它,我們也可以認為,DI是IOC的補充和實現。

工廠和Spring容器

Spring是一個成熟的框架,為了滿足擴展性、實現各種功能,所以它的實現如同枝節交錯的大樹一樣,現在讓我們把視線從Spring本身移開,來看看一個萌芽版的Spring容器怎么實現。

Spring的IOC本質就是一個大工廠,我們想想一個工廠是怎么運行的呢?

如何實現一個萌芽版的Spring容器

生產產品:一個工廠最核心的功能就是生產產品。在Spring里,不用Bean自己來實例化,而是交給Spring,應該怎么實現呢?——答案毫無疑問,反射。

那么這個廠子的生產管理是怎么做的?你應該也知道——工廠模式。

庫存產品:工廠一般都是有庫房的,用來庫存產品,畢竟生產的產品不能立馬就拉走。Spring我們都知道是一個容器,這個容器里存的就是對象,不能每次來取對象,都得現場來反射創建對象,得把創建出的對象存起來。

訂單處理:還有最重要的一點,工廠根據什么來提供產品呢?訂單。這些訂單可能五花八門,有線上簽簽的、有到工廠簽的、還有工廠銷售上門簽的……最后經過處理,指導工廠的出貨。

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

那對應我們的萌芽版的Spring容器是什么樣的呢?

如何實現一個萌芽版的Spring容器

訂單:Bean定義

Bean可以通過一個配置文件定義,我們會把它解析成一個類型。

如何實現一個萌芽版的Spring容器

  • beans.properties

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

userDao:cn.fighter3.bean.UserDao

  • BeanDefinition.java

bean定義類,配置文件中bean定義對應的實體

public class BeanDefinition {

    private String beanName;

    private Class beanClass;
     //省略getter、setter  
 }

獲取訂單:資源加載

接下訂單之后,就要由銷售向生產部門交接,讓生產部門知道商品的規格、數量之類。

資源加載器,就是來完成這個工作的,由它來完成配置文件中配置的加載。

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注冊

對象注冊器,這里用于單例bean的緩存,我們大幅簡化,默認所有bean都是單例的。可以看到所謂單例注冊,也很簡單,不過是往HashMap里存對象。

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);
    }

    /**
     * 注冊單例bean
     *
     * @param beanName
     * @param bean
     */
    public void registerSingletonBean(String beanName, Object bean) {
        if (singletonMap.containsKey(beanName)) {
            return;
        }
        singletonMap.put(beanName, bean);
    }

}

生產車間:對象工廠

好了,到了我們最關鍵的生產部門了,在工廠里,生產產品的是車間,在IOC容器里,生產對象的是BeanFactory。

如何實現一個萌芽版的Spring容器

對象工廠,我們最核心的一個類,在它初始化的時候,創建了bean注冊器,完成了資源的加載。

獲取bean的時候,先從單例緩存中取,如果沒有取到,就創建并注冊一個bean

public class BeanFactory {

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

    private BeanRegister beanRegister;

    public BeanFactory() {
        //創建bean注冊器
        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;
        }
        //根據bean定義,創建bean
        return createBean(beanDefinitionMap.get(beanName));
    }

    /**
     * 創建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;
    }
}

生產銷售:測試

UserDao.java

我們的Bean類,很簡單

public class UserDao {

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

單元測試

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

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

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

運行結果

A good man.
A good man.

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

以上是“如何實現一個萌芽版的Spring容器”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

堆龙德庆县| 进贤县| 天水市| 涟源市| 盐源县| 阳东县| 余江县| 城步| 高密市| 铜梁县| 盐池县| 天津市| 彰化市| 长子县| 缙云县| 兰溪市| 杂多县| 民和| 吉林市| 博爱县| 浏阳市| 遂宁市| 宁陵县| 胶南市| 大田县| 长丰县| 五台县| 博客| 赤峰市| 澳门| 黎平县| 科尔| 贵南县| 秦皇岛市| 太仆寺旗| 信丰县| 中超| 韩城市| 宁晋县| 南投县| 扬州市|