|
package ch5.LookupMethod;
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
package ch5.LookupMethod;
public class MyHelper ...{ public void doSomething()...{ } }
以下是两个singleton bean的实现接口
package ch5.LookupMethod;
public interface DemoBean ...{ public MyHelper getmyHelper(); public void someOperation(); }
以下代码是StandardLookupDemoBean使用setter方式获得MyHelper bean
package ch5.LookupMethod;
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
之所以定义成抽象类,后面会有论述
package ch5.LookupMethod;
public abstract class AbstractLoopipMethodDemoBean implements DemoBean ...{
public abstract MyHelper getmyHelper(); public void someOperation() ...{ getmyHelper().doSomething(); }
}
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <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>
测试代码:
package ch5.LookupMethod;
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,但还是建议这样做,可以防止不小心忘了配置查找方法而留一个空方法在代码中
|