[spring]從頭開始-lookup method Injection

開發工具:IntelliJ IDEA 13

開發環境:jdk1.6.0_45

Framework:spring 3

一般bean的注入除了xml/Annotation 來產生instance,還有其他方法可用,在配置檔中使用 lookup-method 來讓spring 找尋對應 method 的 instance

首先建立測試用類別 MyHelper

MyHelper.java

package foo.bar;

/**

 * Created by Hsu on 2014/7/11.

 */

public class MyHelper {

    public void doSomethingHelpful(){

        //System.out.println("Do something!!!");

    }

}

接著在建立一個 interface DemoBean

DemoBean.java

package foo.bar;

/**

 * Created by Hsu on 2014/7/11.

 */

public interface DemoBean {

    public MyHelper getMyHelper();

    public void someOperation();

}

再來我們建立兩個 implements 類別

AbstractLookupDemoBean 及 StandardLookupDemoBean 這兩個類別最大的

差異點在於後者將使用傳統的inject方式來查找對對應的method,前者將使用

look-method來指定要spring執行的method,前者所對應出來的bean,每次都

是不同的實體,後者則為singleton 單一實例

AbstractLookupDemoBean.java

package foo.bar;

/**

 * Created by Hsu on 2014/7/11.

 */

public abstract class AbstractLookupDemoBean implements DemoBean{

    //抽象方法,不做注入部分,由spring依xml指定訊息查找對應實例

    public abstract MyHelper getMyHelper();

    public void someOperation() {

        getMyHelper().doSomethingHelpful();

    }

}

StandardLookupDemoBean.java

package foo.bar;

/**

 * Created by Hsu on 2014/7/11.

 */

public class StandardLookupDemoBean implements DemoBean {

    //採用xml 實例注入

    public MyHelper myHelper;

    public MyHelper getMyHelper() {

        return this.myHelper;

    }

    public void setMyHelper(MyHelper myHelper) {

        this.myHelper = myHelper;

    }

    public void someOperation() {

        myHelper.doSomethingHelpful();

    }

}

接下來是spring-config.xml配置檔部分

spring-config.xml

..

..標頭的部分省略

    <context:annotation-config />

    <context:component-scan base-package="foo.bar"/>

    <bean id="helper" class="foo.bar.MyHelper" scope="prototype" />

    <bean id="abstractLookupBean" class="foo.bar.AbstractLookupDemoBean">

        <!-- 藉由指定lookup-method 去查找對應的 MyHelper 實例 -->

        <lookup-method name="getMyHelper" bean="helper"/>

    </bean>

    <bean id="standardLookupBean" class="foo.bar.StandardLookupDemoBean">

        <property name="myHelper">

            <ref local="helper"/>

        </property>

    </bean>

..結尾省略

最後我們來實現演繹main method的部份

LookupDemo.java

package foo.bar;

import org.springframework.context.support.GenericXmlApplicationContext;

import org.springframework.util.StopWatch;

/**

 * Created by Hsu on 2014/7/11.

 */

public class LookupDemo {

    public static void main(String[] args) {

        GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();

        ctx.load("classpath:spring-config.xml");

        DemoBean abstractBean = (DemoBean) ctx.getBean("abstractLookupBean");

        DemoBean standardBean = (DemoBean) ctx.getBean("standardLookupBean");

        displayInfo(standardBean);

        displayInfo(abstractBean);

    }

    public static void displayInfo(DemoBean bean) {

        MyHelper helper1 = bean.getMyHelper();

        MyHelper helper2 = bean.getMyHelper();

        System.out.println("Helper Instances the Same?: "

                + (helper1 == helper2));

        //StopWatch 為 org.springframework.util 中的好用工具

        //拿來當計數器剛剛好

        StopWatch stopWatch = new StopWatch();

        stopWatch.start("lookupDemo");

        for (int x = 0; x < 100000; x++) {

            MyHelper helper = bean.getMyHelper();

            helper.doSomethingHelpful();

        }

        stopWatch.stop();

        System.out.println("100000 gets took " + stopWatch.getTotalTimeMillis() + " ms");

    }

}

整段的運行結果如下:

Helper Instances the Same?: true

100000 gets took 5 ms

Helper Instances the Same?: false

100000 gets took 642 ms

由上述結果可看到,由 standardBean 所產生的 instance 每次都是一樣的,

而由 abstractBean 產生的 instance 每次都是不同,雖然在xml的配置檔中

有配置注入 bean 的 scope 為 prototype

<bean id="helper" class="foo.bar.MyHelper" scope="prototype" />

但實際對於 standardBean  所產生的結果不會有任何影響,因為一般注入就是

signleton 單一實例,

但若改為 <bean id="helper" class="foo.bar.MyHelper" scope="signleton" />

則會發現結果變為;

Helper Instances the Same?: true

100000 gets took 3 ms

Helper Instances the Same?: true

100000 gets took 224 ms

連look-method 所查找出來的實例也變成了 signleton,比較一下兩個方法

所花費的時間,對於小程式來說可能無關痛癢,但對於大型的站台,在

time cost 上就差距很多,而且signleton 及 prototype 也有相當的差距,

在運用上,建議依照實際需求去做調整。

demo程式(右鍵另開視窗下載)