免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
自制IOC容器(2)

本系列文章介紹ByxContainer的實(shí)現(xiàn)思路。

ByxContainer是一個(gè)簡(jiǎn)單的輕量級(jí)IOC容器,具有以下特性:

  • 使用JSON格式的配置文件
  • 支持構(gòu)造函數(shù)注入、靜態(tài)工廠注入、實(shí)例工廠注入、屬性注入、setter注入、條件注入
  • 組件的延遲加載和單例組件
  • 根據(jù)id注冊(cè)、獲取容器中的組件

ByxContainer的設(shè)計(jì)借鑒了ajoo大神的博客。

項(xiàng)目地址:github 碼云

本篇文章介紹ByxContainer中與對(duì)象創(chuàng)建有關(guān)的設(shè)計(jì)。

對(duì)象的創(chuàng)建方式

要解決上面的問(wèn)題,我們需要思考:創(chuàng)建一個(gè)對(duì)象到底有多少種方法呢?

在Java中,創(chuàng)建一個(gè)對(duì)象主要有以下三種方法:

  • 構(gòu)造函數(shù)
  • 靜態(tài)工廠
  • 實(shí)例工廠

最常用的創(chuàng)建對(duì)象的方式,肯定是構(gòu)造函數(shù)了:

A a = new A("hello", 123);

靜態(tài)工廠方式,就是通過(guò)調(diào)用某個(gè)工廠類(lèi)的靜態(tài)方法來(lái)創(chuàng)建對(duì)象,常用于工廠模式:

A a = Factory.create("hello", 123);

實(shí)例工廠方式,則是通過(guò)調(diào)用某個(gè)工廠類(lèi)的實(shí)例方法來(lái)創(chuàng)建對(duì)象:

Factory factory = new Factory();
A a = factory.create("hello", 123);

對(duì)于最后一種實(shí)例工廠方式,有的人可能覺(jué)得很陌生,但是實(shí)際上,我們?cè)贘ava中調(diào)用的大多數(shù)方法都是實(shí)例工廠。其實(shí),凡是通過(guò)對(duì)象實(shí)例調(diào)用并且返回一個(gè)值的方法都屬于實(shí)例工廠,即使這個(gè)方法與創(chuàng)建對(duì)象并沒(méi)有語(yǔ)義上的關(guān)系,如Stringsubstring,或者Listget

其實(shí)這里還漏了一種方式,那就是:我們不需要容器來(lái)幫我們創(chuàng)建對(duì)象,而是直接把創(chuàng)建好的對(duì)象交給容器,到時(shí)候讓容器直接返回這個(gè)對(duì)象就行了。什么時(shí)候需要用這種方式呢?比如說(shuō),我們想在容器中放一個(gè)整數(shù)123,但我們并不希望到時(shí)候讓容器調(diào)用new java.lang.Integer(123)來(lái)創(chuàng)建這個(gè)整數(shù),而是希望容器直接返回一個(gè)123給我們。如果這里不理解,可以直接看下面ValueComponent的實(shí)現(xiàn)。

封裝通用Component實(shí)現(xiàn)類(lèi)

既然歸納出了上面四種創(chuàng)建對(duì)象的方式,那么我們是不是可以對(duì)這四種方式分別封裝一個(gè)通用的Component實(shí)現(xiàn)類(lèi)呢?這樣,假如用戶(hù)恰好需要使用這四種方式之一來(lái)創(chuàng)建對(duì)象,就可以直接使用我們寫(xiě)好的實(shí)現(xiàn)類(lèi),而不用自己編寫(xiě)實(shí)現(xiàn)類(lèi)了。

首先是最簡(jiǎn)單的ValueComponent,它封裝了已經(jīng)創(chuàng)建出來(lái)的對(duì)象:

public class ValueComponent implements Component
{
    private final Object value;

    public ValueComponent(Object value)
    {
        this.value = value;
    }

    @Override
    public Object create()
    {
        return value;
    }
}

為了使用更方便,可以在Component接口定義中添加一個(gè)靜態(tài)方法value

public interface Component
{
    ...
    static Component value(Object value)
    {
        return new ValueComponent(value);
    }
}

這樣,只要靜態(tài)導(dǎo)入了Component,就可以直接寫(xiě)下面的代碼:

Component intValue = value(123);
Component stringValue = value("hello");

然后是ConstructorComponent

public class ConstructorComponent implements Component
{
    private final Class<?> type;
    private final Component[] params;

    public ConstructorComponent(Class<?> type, Component... params)
    {
        this.type = type;
        this.params = params;
    }

    @Override
    public Object create()
    {
        // 獲取參數(shù)
        Object[] p = Arrays.stream(params).map(Component::create).toArray();
        
        // 調(diào)用type的構(gòu)造函數(shù),并傳遞參數(shù)
        ...
    }
}

public interface Component
{
    ...
    static Component constructor(Class<?> type, Component... params)
    {
        return new ConstructorComponent(type, params);
    }
}

ConstructorComponent需要一個(gè)type用來(lái)指明調(diào)用哪個(gè)類(lèi)的構(gòu)造函數(shù),params用來(lái)傳遞構(gòu)造函數(shù)的參數(shù)。注意,params的類(lèi)型是Component[],而不是Object[],為什么呢?因?yàn)闃?gòu)造函數(shù)的參數(shù)也可能是一個(gè)被IOC容器管理的組件,例如:

B b = new B();
A a = new A(b);

這里ab都是IOC容器中的組件,可以這樣來(lái)聲明這兩個(gè)組件:

Component b = constructor(B.class);
Component a = constructor(A.class, b);

如果想向構(gòu)造函數(shù)傳遞常數(shù),可以用ValueComponent包裝一下:

// A a = new A("hello", 123);
Component a = constructor(value("hello"), value(123));

接著是StaticFactoryComponent

public class StaticFactoryComponent implements Component
{
    private final Class<?> type;
    private final String method;
    private final Component[] params;

    public StaticFactoryComponent(Class<?> type, String method, Component[] params)
    {
        this.type = type;
        this.method = method;
        this.params = params;
    }

    @Override
    public Object create()
    {
        // 獲取參數(shù)
        Object[] p = Arrays.stream(params).map(Component::create).toArray();

        // 調(diào)用type的靜態(tài)method方法,并傳遞參數(shù)
        ...
    }
}

public interface Component
{
    ...
    static Component staticFactory(Class<?> type, String method, Component... params)
    {
        return new StaticFactoryComponent(type, method, params);
    }
}

type是工廠類(lèi)的Class,methor是工廠方法名,params是方法參數(shù)。

最后是InstanceFactoryComponent

public class InstanceFactoryComponent implements Component
{
    private final Component instance;
    private final String method;
    private final Component[] params;

    public InstanceFactoryComponent(Component instance, String method, Component[] params)
    {
        this.instance = instance;
        this.method = method;
        this.params = params;
    }

    @Override
    public Object create()
    {
        // 獲取實(shí)例和參數(shù)
        Object i = instance.create();
        Object[] p = Arrays.stream(params).map(Component::create).toArray();

        // 調(diào)用i的實(shí)例method方法,并傳遞參數(shù)
        ...
    }
}

public interface Component
{
    ...
    static Component instanceFactory(Component instance, String method, Component... params)
    {
        return new InstanceFactoryComponent(instance, method, params);
    }
}

instance是創(chuàng)建實(shí)例的組件,method是實(shí)例方法名,params是方法參數(shù)。

使用ByxContainer

到這里,與創(chuàng)建對(duì)象有關(guān)的操作就完成得差不多了,對(duì)于一些常規(guī)的創(chuàng)建對(duì)象的需求,ByxContainer都能很好地應(yīng)對(duì)。下面給出一些使用示例:

// A a = new A();
Component a = constructor(A.class);

// A a = new A("hello", 123);
Component a = constructor(value("hello"), value(123));

// A a = Factory.createDefault();
Component a = staticFactory(Factory.class, "createDefault");

// A a = Factory.create("hello", 123);
Component a = staticFactory(Factory.class, "create", value("hello"), value(123));

// B b = new B();
// A a = b.create("hello", 123);
Component b = construct(B.class);
Component a = instanceFactory(b, "create", value("hello"), value(123));

// A a = new B().create("hello", 123);
Component a = instanceFactory(constructor(B.class), "create", value("hello"), value(123));
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶(hù)發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Spring 核心組件工作原理簡(jiǎn)析
如何自行分析SAP WebClient UI開(kāi)發(fā)環(huán)境里拋出的錯(cuò)誤消息根源
Java反射機(jī)制的原理及在Android下的簡(jiǎn)單應(yīng)用
Java反射機(jī)制的學(xué)習(xí)
CXF客戶(hù)端請(qǐng)求服務(wù)流程,cxf客戶(hù)端服務(wù)流程
Java中如何動(dòng)態(tài)創(chuàng)建接口的實(shí)現(xiàn)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服