public interface DemoBean ... {
public MyHelper getmyHelper();
public void someOperation();
}
Spring使用CGLIB的动态字节码增强功能,所以,必须要加入CGLIB包
当Bean依赖另一个生命周期不同的bean,尤其是当singleton依赖一个non-singleton时,常会遇到不少问题,Lookup Method Injection正是对付这些问题而出现的,在上述情况中,setter和构造注入都回导致singleton去维护一个non-singleton bean的单个实例,某些情况下,我们希望让singleton bean每次要求获得bean时候都返回一个non-singleton bean的新实例
Myhelper Bean
public class MyHelper ... {
public void doSomething()...{
}
}
以下是两个singleton bean的实现接口
public interface DemoBean ... {
public MyHelper getmyHelper();
public void someOperation();
}
以下代码是StandardLookupDemoBean使用setter方式获得MyHelper bean
public class StandardLookupDemoBean implements DemoBean ... {
private MyHelper myHelper;
public void setMyHelper(MyHelper myHelper) ...{
this.myHelper = myHelper;
}
public MyHelper getmyHelper() ...{
return this.myHelper;
}
public void someOperation() ...{
myHelper.doSomething();
}
}
以下是使用Lookup Method的abstract class
之所以定义成抽象类,后面会有论述
public abstract class AbstractLoopipMethodDemoBean implements DemoBean ... {
public abstract MyHelper getmyHelper();
public void someOperation() ...{
getmyHelper().doSomething();
}
}
配置文件:
< beans
xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" >
< bean id ="helper" class ="ch5.LookupMethod.MyHelper" scope ="prototype" > <!-- spring2.0使用scope="singleton/prototype代替singleton="true/false" -->
</ bean >
< bean id ="standardBean" class ="ch5.LookupMethod.StandardLookupDemoBean" >
< property name ="myHelper" >
< ref local ="helper" />
</ property >
</ bean >
< bean id ="abstractBean" class ="ch5.LookupMethod.AbstractLoopipMethodDemoBean" >
< lookup-method name ="getmyHelper" bean ="helper" />
</ bean >
</ beans >
测试代码:
import java.io.File;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.util.StopWatch;
public class TestSpring ... {
public static void main(String args[]) throws Exception...{
//获取bean factory
ConfigurableListableBeanFactory factory=(ConfigurableListableBeanFactory)getBeanFactory(); //使用子beanFactory
DemoBean standardBean=(DemoBean)factory.getBean("standardBean");
DemoBean abstractBean=(DemoBean)factory.getBean("abstractBean");
displayInfo(standardBean);
displayInfo(abstractBean);
}
public static BeanFactory getBeanFactory()...{
//获取bean factory
String realpath="";
//加载配置项
realpath=System.getProperty("user.dir")+File.separator+"src"+File.separator+"ch5/LookupMethod"+File.separator+"applicationContext.xml";
ConfigurableListableBeanFactory factory=new XmlBeanFactory(new FileSystemResource(realpath));
return factory;
}
public static void displayInfo(DemoBean bean)...{
MyHelper helper1=bean.getmyHelper();
MyHelper helper2=bean.getmyHelper();
System.out.println("Helper instance the same:"+(helper1==helper2));
StopWatch stopWatch=new StopWatch();
stopWatch.start("TestSpring");
for (int i = 0; i < 1000000; i++) ...{
MyHelper helper=bean.getmyHelper();
helper.doSomething();
}
stopWatch.stop();
System.out.println(stopWatch.getTotalTimeMillis());
}
}
结果:
Helper instance the same:true
16
Helper instance the same:false
3594
结果说明:
对于StandardLookupDemoBean,单个MyHelper实例通过setter注入,且这个实例保存下来,所以为true
对于AbstractLoopipMethodDemoBean,每次调用getMyHelper()时候都会返回新实例,所以为false
StopWatch是spring提供的一个测试程序效率的工具类
注意事项:
1.应用场合:需要处理两个生命周期不同的bean时候使用
2.假定你有三个singleton,公用一个依赖,希望每个singleton有自己的实例依赖,所以将依赖设置成singleton,但
实际上每个singleton在其生命周期中使用协作着的同一个实例足以,这种情况下,setter是最好的选择,使用方
法查找注入会增加不必要的开销
3.我们也可以使用实现BeanFactoryAware的方式代替Lookup Method Injection
public void setBeanFactory(Beanfactory factory){
this.factory=factory;
}
public MyHelper getMyHelper(){
return (MyHelper)factory.getBean("helper");
}
使用上述方法在效率上和使用本例的方法,相差无机(100000次差别在几毫秒),所以,建议使用本里的方法,减少和spring api的耦合
4.尽管可以不把查找方法定义成abstract,但还是建议这样做,可以防止不小心忘了配置查找方法而留一个空方法在代码中