lookup-method (2)

转自: http://tjc.iteye.com/blog/339354


情景设定:
    首先简单介绍一下Spring的Bean作用域
   

Spring reference 写道
作用域                 描述
singleton      在每个Spring IoC容器中一个bean定义对应一个对象实例。

prototype      一个bean定义对应多个对象实例。


request        在一次HTTP请求中,一个bean定义对应一个实例;即每次HTTP请求将会有各 自的bean实例, 它们

                      依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效。

session        在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web

                      的Spring ApplicationContext情 形下有效。

global session         在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet

                          context的时候有效。该作用域仅在基于web的Spring ApplicationContext情形下有效。


以上就是Spring对于容器中bean的几种作用域含义的简单描述。我们重点关注一下singleton,prototype这两种作用域。
    ★★关于singleton:

Spring reference 写道
The scope of the Spring singleton is best described as per container and per bean. This means that if you define one bean for a particular class in a single Spring container, then the Spring container will create one and only one instance of the class defined by that bean definition. The singleton scope is the default scope in Spring.


引用
把Spring的 singleton作用域描述成一个container对应一个bean实例最为贴切。亦即,假如在单个Spring容器内定义了某个指定class的 bean,那么Spring容器将会创建一个且仅有一个 由该bean定义指定的类实 例。Singleton作用域是Spring中的缺省作用域。


use it like this

引用
<bean id="beanId" class="com.yourcompany.project.Bean" scope="singleton" />


or

引用
<bean id="beanId" class="com.yourcompany.project.Bean" singleton="true" />



    ★★关于prototype:

Spring reference 写道

The non-singleton, prototype scope of bean deployment results in the creation of a new bean instance every
time a request for that specific bean is made (that is, it is injected into another bean or it is requested via a programmatic getBean() method call on the container). As a rule of thumb, you should use the prototype scope for all beans that are stateful, while the singleton scope should be used for stateless beans.


引用
Prototype作用域 的bean会导致在每次 对该bean请求(将其注入到另一个bean中,或者以程序 的方式调用容器的getBean()方法)时都会创建一个新的 bean实例。根据经 验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。


use it like this

引用
<bean id="beanId" class="com.yourcompany.project.Bean" scope="prototype" />


or

引用
<bean id="beanId" class="com.yourcompany.project.Bean" singleton="false" />


顺便注意一下:

引用
对 prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。

更多请参考Spring reference 3.4.2. The prototype scope

OK,问题出来了

引用
当使用依 赖于prototype bean的singleton-scoped bean时,请注意依赖是在实例化时处理的。这也就是说,如果要把一个prototype-scoped bean注入到singleton-scoped bean,实际上只是实例化一个新的prototype bean注入到 singleton bean...但这是全部。这种情况下,singleton-scoped bean获得的prototype实例是唯一的。

然而,你可能需要在运行期让singleton-scoped bean每次都获得prototype-scoped bean的新实例。在这种情况下,只将prototype-scoped bean注入到你的singleton bean中是没有用的,因为正如上文所说的,仅仅在当Spring容器实例化singleton bean并且处理注入的依赖时,生成唯一实例。


这种情况改怎么解决呢?
oh,我不用Spring 行吗? 行,你又回到起点了....

Spring 为我们提供了方法注入lookup-method 来解决这个问题。我们来体验一下。
一下code参考http://java.ccidnet.com/art/3739/20060317/481857_1.html

在之前搭建的环境的基础上添加cglib库,copy SPRING_HOME/lib/cglib-2.1_x.jar to classpath.
新建com.ufinity.spring.lookupmethod package;
编写如下文件
Hello.java

public interface Hello {
    public Random getRandom();
    public abstract Random createRandom();
}

HelloAbstract.java

public abstract class HelloAbstract implements Hello {
    private Random random;

    public Random getRandom() {
        return random;
    }

    public void setRandom(Random random) {
        this.random = random;
    }

    public abstract Random createRandom();
}

 Random.java

public class Random {
    private int i = (int) (100 * Math.random());

    public void printRandom() {
        System.out.println("输出随机整数:  " + i);
    }
}

配置你的bean 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    <bean id="ran" class="com.ufinity.spring.lookupmethod.Random" scope="prototype"/>
    
    <bean id="hello" class="com.ufinity.spring.lookupmethod.HelloAbstract">
        <lookup-method name="createRandom" bean="ran"/>
        <property name="random">
            <ref local="ran"/>
        </property>
    </bean>
    
</beans>

OK,just test
LookUpMethodTest.java

public class LookUpMethodTest {
	@Test
	public  void testLookupMethod() {

        Resource res = new ClassPathResource("applicationContext-lookupmethod.xml");
        BeanFactory ft = new XmlBeanFactory(res);

        Hello h = (Hello) ft.getBean("hello");

        Random r1 = h.getRandom();
        Random r2 = h.getRandom();
        System.out.println("没有采用Lookup方法注入:");
        System.out.println("Random 的两个实例指向同一个引用:" + (r1 == r2));
        r1.printRandom();
        r2.printRandom();

        Random r3 = h.createRandom();
        Random r4 = h.createRandom();
        System.out.println("\n采用Lookup方法注入:");
        System.out.println("Random 的两个实例指向同一个引用:" + (r3 == r4));
        r3.printRandom();
        r4.printRandom();

    }

}

output:

引用
没有采用Lookup方法 注入:
Random 的两个实例指向同一个引用:true
输出随机整数:  65
输出随机整数:  65

采用Lookup方法注入:

Random 的两个实例指向同一个引用:false
输出随机整数:  97
输出随机整数:  69

 



 

 

 

 

 

 

 

 

 

你可能感兴趣的:(spring,AOP,bean,Web,prototype)