`
gaddma
  • 浏览: 17154 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

spring bean的四种常用作用域的测试

阅读更多

Spring的 bean有5种作用域分别是:singleton、prototype、request、session和globalSession

简单介绍:

spring 起初的版本只有singleton,也就是是否是单例模式。

作用域包括:
singleton
全局只有一个实例
prototype
每次调用产生一个新的实例
在web使用的时候还有三个作用域,但是必须在web.xml中注册一个RequestContextListener , 目的是为了设置每次请求开始和结束都可以使spring得到相应的事件。
request
每次请求产生一个bean
session
每个用户session可以产生一个新的bean,不同用户之间的bean互相不影响
globalSession
作用和session类似,只是使用portlet的时候使用。
测试用例

因为平时使用SPRING MVC开发的时候比较多,有必要了解清楚怎么去调用这几种作用域。

1,定义不同作用域的java类

 

 

@Component
@Scope( "session")
public class SessionObj {

}
@Component
@Scope( "request")
public class RequestObj {

}
@Component
@Scope( "prototype")
public class PrototypeObj {

}
@Component
@Scope( "singleton")
public class SingletonObj {

}

 2,注入到controller,由于controller是单例的,因此必须通过实现ApplicationContextAware接口,直接从容器中取出对象。

 

因此测试的controller是:

 

@Controller
public class IndexController implements ApplicationContextAware {

	private RequestObj RequestObj;

	private SessionObj SessionObj;

	private PrototypeObj PrototypeObj;

	private SingletonObj SingletonObj;

	private ApplicationContext applicationContext;

	@RequestMapping("/")
	@ResponseBody
	public String index() {
		print();
		return "Welcome";
	}

	public void print() {
		System.out.println("first  time singleton is :" + getSingletonObj());
		System.out.println("second time singleton is :" + getSingletonObj());

		System.out.println("first  time prototype is :" + getPrototypeObj());
		System.out.println("second time prototype is :" + getPrototypeObj());

		System.out.println("first  time request is :" + getRequestObj());
		System.out.println("second time request is :" + getRequestObj());

		System.out.println("first  time session is :" + getSessionObj());
		System.out.println("second time session is :" + getSessionObj());
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.applicationContext = applicationContext;
	}

	public RequestObj getRequestObj() {
		return applicationContext.getBean(RequestObj.class);
	}

	public void setRequestObj(RequestObj requestObj) {
		RequestObj = requestObj;
	}

	public SessionObj getSessionObj() {
		return applicationContext.getBean(SessionObj.class);
	}

	public void setSessionObj(SessionObj sessionObj) {
		SessionObj = sessionObj;
	}

	public PrototypeObj getPrototypeObj() {
		return applicationContext.getBean(PrototypeObj.class);
	}

	public void setPrototypeObj(PrototypeObj prototypeObj) {
		PrototypeObj = prototypeObj;
	}

	public SingletonObj getSingletonObj() {
		return applicationContext.getBean(SingletonObj.class);
	}

	public void setSingletonObj(SingletonObj singletonObj) {
		SingletonObj = singletonObj;
	}

}

 

 

3,运行结果:

 

//使用chrome第一次打印数据:
first  time singleton is :com.fb.po.SingletonObj@1e3223e
second time singleton is :com.fb.po.SingletonObj@1e3223e
first  time prototype is :com.fb.po.PrototypeObj@3e683f
second time prototype is :com.fb.po.PrototypeObj@12e18d7
first  time request is :com.fb.po.RequestObj@1d45706
second time request is :com.fb.po.RequestObj@1d45706
first  time session is :com.fb.po.SessionObj@9a6b2e
second time session is :com.fb.po.SessionObj@9a6b2e



//使用chrome打印第二次数据
first  time singleton is :com.fb.po.SingletonObj@1e3223e
second time singleton is :com.fb.po.SingletonObj@1e3223e
first  time prototype is :com.fb.po.PrototypeObj@122e5be
second time prototype is :com.fb.po.PrototypeObj@192add
first  time request is :com.fb.po.RequestObj@4d1b6c
second time request is :com.fb.po.RequestObj@4d1b6c
first  time session is :com.fb.po.SessionObj@9a6b2e
second time session is :com.fb.po.SessionObj@9a6b2e



//使用IE打印第三次数据
first  time singleton is :com.fb.po.SingletonObj@1e3223e
second time singleton is :com.fb.po.SingletonObj@1e3223e
first  time prototype is :com.fb.po.PrototypeObj@10f1ecb
second time prototype is :com.fb.po.PrototypeObj@1aeb990
first  time request is :com.fb.po.RequestObj@18a1e7
second time request is :com.fb.po.RequestObj@18a1e7
first  time session is :com.fb.po.SessionObj@12d5c55
second time session is :com.fb.po.SessionObj@12d5c55

 

 

4,结果分析:

从结果来看,单例的bean的三次的数据都是打印一样的(默认的bean的级别就是单例);

prototype的bean每次的数据都是不一样的,每次请求的时候调用两次结果都不一样。

request的bean在每次request的时候都不一致,但是同一次request返回的数据是一致的。

session的bean在前两次结果一致,最后一次数据不一致,和session的节奏是一致的。

 

5,欠缺

 

网络上说必需配置

<listener> 
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> 
</listener> 

 但是没配置也好使……好奇……

 

最后一种作用域是适用于portlet,没试验,据说是在多个session之间可以共享,效果等同于全局变量。

 

 

 

感谢朴老师,我们有了另外一种测试方式

测试代码

 

@Controller
@Scope("prototype")
public class SecondController {

	@Autowired
	private RequestObj RequestObj;

	@Autowired
	private SessionObj SessionObj;

	@Autowired
	private PrototypeObj PrototypeObj;

	@Autowired
	private SingletonObj SingletonObj;

	@RequestMapping("/test")
	@ResponseBody
	public String index() {
		print();
		return "Welcome";
	}

	public void print() {
		System.out.println("first  time singleton is :" + SingletonObj);
		System.out.println("second time singleton is :" + SingletonObj);

		System.out.println("first  time prototype is :" + PrototypeObj);
		System.out.println("second time prototype is :" + PrototypeObj);

		System.out.println("first  time request is :" + RequestObj);
		System.out.println("second time request is :" + RequestObj);

		System.out.println("first  time session is :" + SessionObj);
		System.out.println("second time session is :" + SessionObj);
	}

}

 

打印的结果是:

first  time singleton is :com.fb.po.SingletonObj@83ca19
second time singleton is :com.fb.po.SingletonObj@83ca19
first  time prototype is :com.fb.po.PrototypeObj@4961d6
second time prototype is :com.fb.po.PrototypeObj@4961d6
first  time request is :com.fb.po.RequestObj@1b6467f
second time request is :com.fb.po.RequestObj@1b6467f
first  time session is :com.fb.po.SessionObj@1ce5037
second time session is :com.fb.po.SessionObj@1ce5037


first  time singleton is :com.fb.po.SingletonObj@83ca19
second time singleton is :com.fb.po.SingletonObj@83ca19
first  time prototype is :com.fb.po.PrototypeObj@1089e03
second time prototype is :com.fb.po.PrototypeObj@1089e03
first  time request is :com.fb.po.RequestObj@be12fc
second time request is :com.fb.po.RequestObj@be12fc
first  time session is :com.fb.po.SessionObj@1ce5037
second time session is :com.fb.po.SessionObj@1ce5037


first  time singleton is :com.fb.po.SingletonObj@83ca19
second time singleton is :com.fb.po.SingletonObj@83ca19
first  time prototype is :com.fb.po.PrototypeObj@a7b674
second time prototype is :com.fb.po.PrototypeObj@a7b674
first  time request is :com.fb.po.RequestObj@bb9ce2
second time request is :com.fb.po.RequestObj@bb9ce2
first  time session is :com.fb.po.SessionObj@138ea04
second time session is :com.fb.po.SessionObj@138ea04

 

 

结果分析:

singleton , request 和session结果都是上面一致,但是prototype结果是和request效果一致的。所以如果要拿到prototype类型的数据的话,应该每次需要都去容器中去拿,而不是注入。

 

 

另,现在开发应用大多数都是无状态的,所以单例多线程是比较好的实现方式,多例的比较有利于保存状态,完全没必要。不过试验JVM垃圾回收,这不就是传说中朝生夕灭的对象吗。

参考http://haohaoxuexi.iteye.com/blog/1190526

 

分享到:
评论
2 楼 85977328 2014-03-26  
另外不太清楚portlet是啥东西
1 楼 85977328 2014-03-26  
文章写的太好了。转载了~~~

相关推荐

Global site tag (gtag.js) - Google Analytics