转自: http://tjc.iteye.com/blog/339354
情景设定:
首先简单介绍一下Spring的Bean作用域
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:
use it like this
or
★★关于prototype:
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.
use it like this
or
顺便注意一下:
更多请参考Spring reference 3.4.2. The prototype scope
OK,问题出来了
然而,你可能需要在运行期让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:
Random 的两个实例指向同一个引用:true
输出随机整数: 65
输出随机整数: 65
采用Lookup方法注入:
Random 的两个实例指向同一个引用:false
输出随机整数: 97
输出随机整数: 69