2015年9月10日 星期四

透過 Guice 入門 Dependency Injection(一)

Guice 是一個可以用來取代原本 Java 程式設計師習慣使用的 Factory 的套件
某種程度上也可以算是一個輕量級的 Spring,能夠動態地做實作類別的注入。
關於 Guice 的開發動機,可以參考 GitHub 上說明動機的頁面 [1]。
另外如果想知道關於 Guice 開發團隊自己怎麼看 Guice 和 Spring,可以參考 [2]。


    Guice 入門
    1、設定 Maven
    要在專案中使用 Guice,必須先把相關的套件引入專案。如果有使用 Maven 的話,可以在 pom.xml 加入下述的 XML。
    <dependency>
        <groupId>com.google.inject</groupId>
        <artifactId>guice</artifactId>
        <version>4.0</version>
    </dependency>
    

    PS. 這裡使用的 Guice 是近幾個月剛釋出的 Guice 4.0。

    2、建立預期要被自動注入的介面與對應的實作類別

    因為 Guice 會執行注入,注入的標的是介面
    所以要先建立介面(MyInterface),以及要作為該介面的實作類別(ImplementationA)。

    /**
     * Interface which can be injected automatically.
     */
    public static interface MyInterface {
        /**
         * Get the class name of the implementation.
         * @return
         */
        public String getClassName();
    }
     
    /**
     * An implementation for MyInterface.
     */
    public static class ImplementationA implements MyInterface {
        @Override
        public String getClassName() {
            return "ImplementationA";
        }
    }
    

    這裡假設介面提供的方法是 getClassName() 方法,預期要回覆實作類別的類別名稱
    因此 ImplementationA 這個實作類別,在 getClassName() 方法的回覆即為 "ImplementationA" 這個字串。

    3、建立 Module 的設定

    在 Guice 中,繼承 AbstractModule 的類別可以用來指派要被注入的介面、以及對應的實作類別
    這些指派的動作必須寫在 configure() 這個方法裡。

    /**
     * Configuring the injection of interfaces.
     */
    public static class MyModule extends AbstractModule {
        @Override
        protected void configure() {
            bind(MyInterface.class).to(ImplementationA.class);
        }
    }
    

    4、建立執行自動注入的類別

    因為 Guice 不會全自動地決定哪些類別要自動進行注入,需要我們事先指定
    因此這裡先建立一個叫做 RunningService 的類別,並且在建構子上加上 @inject 的 Annotation
    表示這個建構子的引數要被注入。

    public class RunningService {
        private MyInterface impl; 
     
        @Inject
        public RunningService (MyInterface myInterface) {
            this.impl = myInterface;
        }
     
        public void print () {
            System.out.println("Implementation of my interface: " + this.impl.getClassName());
        }
    }
    

    RunningService 提供 print() 方法,作為範例中 RunningService 真正要執行的邏輯。
    print() 方法會印出 RunningService 得到的 MyInterface 介面的實作類別名稱。

    5、建立程式進入點

    最後是在 main() 進入點指定要透過 Guice 取得 RunningService 的 instance
    這樣才能讓 Guice 去做好自動注入的行為。

    public static void main(String[] args) {
        // Initiate the injection through Guice.
        Injector injector = Guice.createInjector(new MyModule());
      
        // Use Guice to inject and get the instance.
        RunningService service = injector.getInstance(RunningService.class);
        service.print();
    }

    程式最後執行的結果如下:
    Implementation of my interface: ImplementationA

    參考資料
    1. google/guice/Motivation
    2. google/guice/SpringComparison

    沒有留言: