《Pro Spring》学习笔记之Loopup Method Injection(查找方法注入)

来源:互联网 发布:c语言学生管理系统ppt 编辑:程序博客网 时间:2024/05/04 01:31

 

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,但还是建议这样做,可以防止不小心忘了配置查找方法而留一个空方法在代码中

原创粉丝点击