真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

從零開始手寫springioc框架,深入學(xué)習(xí)spring源碼

IoC

Ioc 是一款 spring ioc 核心功能簡(jiǎn)化實(shí)現(xiàn)版本,便于學(xué)習(xí)和理解原理。

我們提供的服務(wù)有:成都做網(wǎng)站、成都網(wǎng)站建設(shè)、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、明溪ssl等。為上1000+企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的明溪網(wǎng)站制作公司

創(chuàng)作目的

使用 spring 很長(zhǎng)時(shí)間,對(duì)于 spring 使用非常頻繁,實(shí)際上對(duì)于源碼一直沒有靜下心來學(xué)習(xí)過。

但是 spring 源碼存在一個(gè)問題,那就是過于抽象,導(dǎo)致學(xué)習(xí)起來成本上升。

所以本項(xiàng)目由漸入深,只實(shí)現(xiàn) spring 的核心功能,便于自己和他人學(xué)習(xí) spring 的核心原理。

spring 的核心

Spring 的核心就是 spring-beans,后面的一切 spring-boot,spring-cloud 都是建立在這個(gè)地基之上。

當(dāng)別人問你 spring 的時(shí)候,希望你可以談?wù)勛约簩?duì)于 spring ioc 自己更深層的見解,而不是網(wǎng)上人云亦云的幾句話。

什么是 IOC

控制反轉(zhuǎn)(Inversion of Control,縮寫為IoC),是面向?qū)ο缶幊讨械囊环N設(shè)計(jì)原則,可以用來減低計(jì)算機(jī)代碼之間的耦合度。

其中最常見的方式叫做依賴注入(Dependency Injection,簡(jiǎn)稱DI)。

通過控制反轉(zhuǎn),對(duì)象在被創(chuàng)建的時(shí)候,由一個(gè)調(diào)控系統(tǒng)內(nèi)所有對(duì)象的外界實(shí)體,將其所依賴的對(duì)象的引用傳遞給它。

也可以說,依賴被注入到對(duì)象中。

為什么需要 IOC

IoC 是解耦的一種方法。

我們知道Java 是一門面向?qū)ο蟮恼Z言,在 Java 中 Everything is Object,我們的程序就是由若干對(duì)象組成的。

當(dāng)我們的項(xiàng)目越來越大,合作的開發(fā)者越來越多的時(shí)候,我們的類就會(huì)越來越多,類與類之間的引用就會(huì)成指數(shù)級(jí)的增長(zhǎng)。

從零開始手寫 spring ioc 框架,深入學(xué)習(xí) spring 源碼

這樣的工程簡(jiǎn)直就是災(zāi)難,如果我們引入 Ioc 框架。

由框架來維護(hù)類的生命周期和類之間的引用。

我們的系統(tǒng)就會(huì)變成這樣:

從零開始手寫 spring ioc 框架,深入學(xué)習(xí) spring 源碼

這個(gè)時(shí)候我們發(fā)現(xiàn),我們類之間的關(guān)系都由 IoC 框架負(fù)責(zé)維護(hù)類,同時(shí)將類注入到需要的類中。

也就是類的使用者只負(fù)責(zé)使用,而不負(fù)責(zé)維護(hù)。

把專業(yè)的事情交給專業(yè)的框架來完成,大大的減少開發(fā)的復(fù)雜度。

快速開始

maven 引入


    com.github.houbb
    ioc
    0.1.11

測(cè)試準(zhǔn)備

全部測(cè)試代碼,見 test 模塊。

  • Apple.java
public class Apple {

    public void color() {
        System.out.println("Apple color: red. ");
    }

}
  • apple.json

類似于 xml 的配置,我們暫時(shí)使用 json 進(jìn)行配置驗(yàn)證。

[
{"name":"apple","className":"com.github.houbb.ioc.test.service.Apple"}
]

執(zhí)行測(cè)試

  • 測(cè)試
BeanFactory beanFactory = new JsonApplicationContext("apple.json");
Apple apple = (Apple) beanFactory.getBean("apple");
apple.color();
  • 日志
Apple color: red.

spring 基本實(shí)現(xiàn)流程

說明

spring-beans 一切都是圍繞 bean 展開的。

BeanFactory 負(fù)責(zé)對(duì) bean 進(jìn)行生命周期的相關(guān)管理,本節(jié)展示第一小節(jié)的簡(jiǎn)單實(shí)現(xiàn)流程。

spring 核心流程

Spring IoC 主要是以下幾個(gè)步驟。

  1. 初始化 IoC 容器。

  2. 讀取配置文件。

  3. 將配置文件轉(zhuǎn)換為容器識(shí)別對(duì)的數(shù)據(jù)結(jié)構(gòu)(這個(gè)數(shù)據(jù)結(jié)構(gòu)在Spring中叫做 BeanDefinition)

  4. 利用數(shù)據(jù)結(jié)構(gòu)依次實(shí)例化相應(yīng)的對(duì)象

  5. 注入對(duì)象之間的依賴關(guān)系

BeanDefinition 的抽象

BeanDefinition 是 spring 對(duì) java bean 屬性的一個(gè)抽象,經(jīng)過這一層抽象,配置文件可以是 xml/json/properties/yaml 等任意一種,甚至包括注解掃包。

為 spring 的拓展帶來極大的靈活性。

本框架考慮到實(shí)現(xiàn)的簡(jiǎn)單性,初步只實(shí)現(xiàn)了 json 和基于注解掃包兩種方式。

后期如果有時(shí)間可以考慮添加 xml 的實(shí)現(xiàn),其實(shí)更多是 xml 的解析工作量,核心流程已經(jīng)全部實(shí)現(xiàn)。

實(shí)現(xiàn)源碼節(jié)選

BeanDefinition 相關(guān)

包含了對(duì)于 java bean 的基本信息抽象。

  • BeanDefinition.java

其默認(rèn)實(shí)現(xiàn)為 DefaultBeanDefinition.java,就是對(duì)接口實(shí)現(xiàn)的最基本的 java POJO

參見 DefaultBeanDefinition

/**
 * 對(duì)象定義屬性
 * @author binbin.hou
 * @since 0.0.1
 */
public interface BeanDefinition {

    /**
     * 名稱
     * @return 名稱
     * @since 0.0.1
     */
    String getName();

    /**
     * 設(shè)置名稱
     * @param name 名稱
     * @since 0.0.1
     */
    void setName(final String name);

    /**
     * 類名稱
     * @return 類名稱
     */
    String getClassName();

    /**
     * 設(shè)置類名稱
     * @param className 類名稱
     * @since 0.0.1
     */
    void setClassName(final String className);

}

BeanFactory 核心管理相關(guān)

  • BeanFactory.java
/**
 * bean 工廠接口
 * @author binbin.hou
 * @since 0.0.1
 */
public interface BeanFactory {

    /**
     * 根據(jù)名稱獲取對(duì)應(yīng)的實(shí)例信息
     * @param beanName bean 名稱
     * @return 對(duì)象信息
     * @since 0.0.1
     */
    Object getBean(final String beanName);

    /**
     * 獲取指定類型的實(shí)現(xiàn)
     * @param beanName 屬性名稱
     * @param tClass 類型
     * @param  泛型
     * @return 結(jié)果
     * @since 0.0.1
     */
     T getBean(final String beanName, final Class tClass);

}
  • DefaultBeanFactory.java

為接口最基礎(chǔ)的實(shí)現(xiàn),源碼如下:

/**
 * bean 工廠接口
 * @author binbin.hou
 * @since 0.0.1
 */
public class DefaultBeanFactory implements BeanFactory {

    /**
     * 對(duì)象信息 map
     * @since 0.0.1
     */
    private Map beanDefinitionMap = new ConcurrentHashMap<>();

    /**
     * 對(duì)象 map
     * @since 0.0.1
     */
    private Map beanMap = new ConcurrentHashMap<>();

    /**
     * 注冊(cè)對(duì)象定義信息
     * @since 0.0.1
     */
    protected void registerBeanDefinition(final String beanName, final BeanDefinition beanDefinition) {
        // 這里可以添加監(jiān)聽器
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }

    @Override
    public Object getBean(String beanName) {
        Object bean = beanMap.get(beanName);
        if(ObjectUtil.isNotNull(bean)) {
            // 這里直接返回的是單例,如果用戶指定為多例,則每次都需要新建。
            return bean;
        }

        // 獲取對(duì)應(yīng)配置信息
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(ObjectUtil.isNull(beanDefinition)) {
            throw new IocRuntimeException(beanName + " not exists in bean define.");
        }

        // 直接根據(jù)
        Object newBean = createBean(beanDefinition);
        // 這里可以添加對(duì)應(yīng)的監(jiān)聽器
        beanMap.put(beanName, newBean);
        return newBean;
    }

    /**
     * 根據(jù)對(duì)象定義信息創(chuàng)建對(duì)象
     * @param beanDefinition 對(duì)象定義信息
     * @return 創(chuàng)建的對(duì)象信息
     * @since 0.0.1
     */
    private Object createBean(final BeanDefinition beanDefinition) {
        String className = beanDefinition.getClassName();
        Class clazz = ClassUtils.getClass(className);
        return ClassUtils.newInstance(clazz);
    }

    @Override
    @SuppressWarnings("unchecked")
    public  T getBean(String beanName, Class tClass) {
        Object object = getBean(beanName);
        return (T)object;
    }

}

其中 ClassUtils 是基于 class 的反射工具類,詳情見 ClassUtils.java

JsonApplicationContext

基于 json 配置文件實(shí)現(xiàn)的基本實(shí)現(xiàn),使用方式見開始種的例子代碼。

  • JsonApplicationContext.java
/**
 * JSON 應(yīng)用上下文
 * @author binbin.hou
 * @since 0.0.1
 */
public class JsonApplicationContext extends DefaultBeanFactory {

    /**
     * 文件名稱
     * @since 0.0.1
     */
    private final String fileName;

    public JsonApplicationContext(String fileName) {
        this.fileName = fileName;

        // 初始化配置
        this.init();
    }

    /**
     * 初始化配置相關(guān)信息
     *
     * 
     *  new TypeReference>(){}
     * 
* * 讀取文件:https://blog.csdn.net/feeltouch/article/details/83796764 * @since 0.0.1 */ private void init() { InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName); final String jsonConfig = FileUtil.getFileContent(is); List beanDefinitions = JsonBs.deserializeArray(jsonConfig, DefaultBeanDefinition.class); if(CollectionUtil.isNotEmpty(beanDefinitions)) { for (BeanDefinition beanDefinition : beanDefinitions) { super.registerBeanDefinition(beanDefinition.getName(), beanDefinition); } } } }

小結(jié)

至此,一個(gè)最基本的 spring ioc 就基本實(shí)現(xiàn)了。

如果你想繼續(xù)學(xué)習(xí),可以分別參考以下代碼分支。

分支說明

v0.0.1-BeanFactory 基本實(shí)現(xiàn)

v0.0.2-ListBeanFactory 基本實(shí)現(xiàn)

v0.0.3-單例和延遲加載

v0.0.4-初始化和銷毀方法

v0.0.5-RespCode 添加和代碼優(yōu)化

v0.0.6-構(gòu)造器和 factoryMethod 新建對(duì)象

v0.0.7-property 屬性設(shè)置

v0.0.8-Aware 監(jiān)聽器及 PostProcessor

v0.0.9-Parent 屬性繼承

v0.1.0-循環(huán)依賴檢測(cè)

v0.1.1-@Configuration-java 代碼配置

v0.1.2-@Bean-java 對(duì)象定義

v0.1.3-@Lazy-@Scope-java 對(duì)象屬性配置

v0.1.4-@Import 配置導(dǎo)入

v0.1.5-@Bean 參數(shù)構(gòu)造以及 @Description

v0.1.6-@Autowired 自動(dòng)裝配注解支持

v0.1.7-@Primary 指定優(yōu)先級(jí)注解

v0.1.8-@Conditional 條件注解支持

v0.1.9-Environment 和 @Profile 實(shí)現(xiàn)

v0.1.10-Property 配置文件相關(guān)和 @Value/@PropertyResource 實(shí)現(xiàn)

v0.1.11-@ComponentScan 文件包掃描支持

拓展閱讀

Java IOC-00-ioc 是什么


當(dāng)前標(biāo)題:從零開始手寫springioc框架,深入學(xué)習(xí)spring源碼
本文來源:http://weahome.cn/article/gojiih.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部