[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 也有相當的差距,
在運用上,建議依照實際需求去做調整。