乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      自制IOC容器(2)

       怡紅公子0526 2021-05-04

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

      ByxContainer是一個簡單的輕量級IOC容器,具有以下特性:

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

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

      項目地址:github 碼云

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

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

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

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

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

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

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

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

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

      實例工廠方式,則是通過調(diào)用某個工廠類的實例方法來創(chuàng)建對象:

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

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

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

      封裝通用Component實現(xiàn)類

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

      首先是最簡單的ValueComponent,它封裝了已經(jīng)創(chuàng)建出來的對象:

      public class ValueComponent implements Component
      {
          private final Object value;
      
          public ValueComponent(Object value)
          {
              this.value = value;
          }
      
          @Override
          public Object create()
          {
              return value;
          }
      }
      

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

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

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

      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需要一個type用來指明調(diào)用哪個類的構(gòu)造函數(shù),params用來傳遞構(gòu)造函數(shù)的參數(shù)。注意,params的類型是Component[],而不是Object[],為什么呢?因為構(gòu)造函數(shù)的參數(shù)也可能是一個被IOC容器管理的組件,例如:

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

      這里ab都是IOC容器中的組件,可以這樣來聲明這兩個組件:

      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是工廠類的Classmethor是工廠方法名,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ù)
              Object i = instance.create();
              Object[] p = Arrays.stream(params).map(Component::create).toArray();
      
              // 調(diào)用i的實例method方法,并傳遞參數(shù)
              ...
          }
      }
      
      public interface Component
      {
          ...
          static Component instanceFactory(Component instance, String method, Component... params)
          {
              return new InstanceFactoryComponent(instance, method, params);
          }
      }
      

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

      使用ByxContainer

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

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

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多