Spring在bean配置时可以配置scope(bean的作用域),主要用来控制bean的生命周期,在spring2.0之前bean只有2种作用域即:singleton(单例)、non-singleton(也称prototype), Spring2.0以后,增加了session、request、global session三种专用于Web应用程序上下文的Bean。所以,默认情况下Spring2.0现在有五种类型的Bean。
1、singleton
当一个bean的作用域设置为singleton, 那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。换言之,当把一个bean定义设置为singleton作用域时,Spring IOC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都将返回被缓存的对象实例,这里要注意的是singleton作用域和GOF设计模式中的单例是完全不同的,单例设计模式表示一个ClassLoader中只有一个class存在,而这里的singleton则表示一个容器对应一个bean,也就是说当一个bean被标识为singleton时候,spring的IOC容器中只会存在一个该bean。
2、prototype
prototype作用域部署的bean,每一次请求(以程序的方式调用容器的getBean()方法)都会产生一个新的bean实例,相当与一个new的操作,对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。也就是说spring只负责对prototype的bean产生,不负责销毁,这种bean的消息需要自己来处理
3、request
request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效
4、session
session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效
5、global session
global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个portlet web应用的各种不同的portlet所共享。在global session作用域中定义的bean被限定于全局portlet Session的生命周期范围内。如果你在web中使用global session作用域来标识bean,那么web会自动当成session类型来使用。
事实上,在Spring核心中只有singleton和prototype两种作用域,request、session、global session这3种scope都是基于prototype来实现的,对这3种方式产生的bean,spring的核心也是不负责销毁的,负责管理的是他们对应的Scope实现类,而且spring还允许自定义Scope。
request、session、global session使用的时候首先要在初始化web的web.xml中配置对应的listener或者 filter,listener:org.springframework.web.context.request.RequestContextListener(servlet2.4 以上)或者filter:org.springframework.web.filter.RequestContextFilter,这两个类的作用是一样的,就是从java的web Servlet机制中获取请求的HttpServletRequest和HttpSession对象
以request为例:
在RequestContextListener中获取到HttpServletRequest对象,以此来生成ServletRequestAttributes对象,然后把ServletRequestAttributes对象放入RequestContextHolder线程对象中,在调用BeanFactory.getBean()方法时Spring会调用RequestScope.get(String name, ObjectFactory objectFactory)方法,具体代码:
public Object get(String name, ObjectFactory objectFactory) { RequestAttributes attributes = RequestContextHolder.currentRequestAttributes(); Object scopedObject = attributes.getAttribute(name, getScope()); if (scopedObject == null) { scopedObject = objectFactory.getObject(); attributes.setAttribute(name, scopedObject, getScope()); } return scopedObject; },从RequestContextHolder中获取ServletRequestAttributes对象,ServletRequestAttributes.getAttribute(String name, int scope)在request的Scope下就是从HttpServletRequest对象的attribute属性中取值,如果取不到再调用ObjectFactory以prototype方式重新生成一个并放入HttpServletRequest的attribute中,以便下次获取,放HttpServletRequest的bean随着请求的结束,生命周期也就结束了
--------------------------------------------------------
自定义的Scope
Spring允许我们自定义Scope来管理bean,下面有一个简单例子,假设一个bean能被对个request线程复用,但是只能被使用5次(每个线程算一次)
import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.config.Scope; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; public class MyScope implements Scope { private Map<String, ThreadsShareBean> map = new ConcurrentHashMap<String, ThreadsShareBean>(); @Override public Object get(String name, ObjectFactory objectFactory) { RequestAttributes attributes = RequestContextHolder.currentRequestAttributes(); Object scopedObject = attributes.getAttribute(name, RequestAttributes.SCOPE_REQUEST); if (scopedObject == null) { ThreadsShareBean threadsShareBean = this.map.get(name); if (threadsShareBean != null) { scopedObject = threadsShareBean.get(); } if (scopedObject == null) { scopedObject = objectFactory.getObject(); this.map.put(name, new ThreadsShareBean(scopedObject)); } attributes.setAttribute(name, scopedObject, RequestAttributes.SCOPE_REQUEST); } return scopedObject; } public Object remove(String name) { RequestAttributes attributes = RequestContextHolder.currentRequestAttributes(); ThreadsShareBean threadsShareBean = this.map.remove(name); Object scopedObject = attributes.getAttribute(name, RequestAttributes.SCOPE_REQUEST); if (scopedObject != null) { attributes.removeAttribute(name, RequestAttributes.SCOPE_REQUEST); } else { scopedObject = threadsShareBean.obj; } return scopedObject; } public void registerDestructionCallback(String name, Runnable callback) { RequestAttributes attributes = RequestContextHolder.currentRequestAttributes(); attributes.registerDestructionCallback(name, callback, RequestAttributes.SCOPE_REQUEST); } @Override public String getConversationId() { return null; } class ThreadsShareBean { private AtomicInteger atomicInteger = new AtomicInteger(1); private Object obj = null; public ThreadsShareBean(Object obj) { this.obj = obj; } public Object get() { if (atomicInteger.getAndIncrement() < 5) { return obj; } return null; } } }首先要实现org.springframework.beans.factory.config.Scope接口,然后借用了RequestContextHolder的存放当前线程的bean
另外必须在bean初始化之前把MyScope注册到Spring ioc中,否则Spring启动的时候会报错,我是用BeanFactoryPostProcessor来实现的
public class RegisterMyScope implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { beanFactory.registerScope("myScope", new MyScope()); } }最要只要在spring配置文件中注册这个bean就可以了
相关推荐
今天,我们将深入探讨 RequestScope 的用途和实现细节,以及与其他作用域(ApplicationScope、SessionScope、ViewScope)的比较。 RequestScope 的工作机理是将变量保存在当前 HTTP 请求的生命周期内,这意味着变量...
pageScope、requestScope、sessionScope、applicationScope区别
这两个Bean都继承自`HelloMessageGenerator`类,并且分别使用了`@RequestScope`和`@SessionScope`注解来指定它们的作用域。 1. `@RequestScope`:这个注解表示Bean的生命周期与每个HTTP请求关联。每当一个新的HTTP...
org.springframework.web.context.request.RequestScope.class org.springframework.web.context.request.ServletRequestAttributes.class org.springframework.web.context.request.ServletWebRequest.class org....
本文将对jsp的四个作用域:pageScope、requestScope、sessionScope和applicationScope进行详细的解释和比较。 pageScope是jsp的最小作用域,仅在当前页面有效。在一个jsp页面里有效,变量可以在当前页面中使用,...
- **与范围有关的隐含对象**:pageScope、requestScope、sessionScope和applicationScope对应JSP的pageContext、request、session和application对象,用于获取范围内的属性值。 - **与输入有关的隐含对象**:param...
4. **属性范围**:在EL中有四种默认的属性范围:PageScope、RequestScope、SessionScope和ApplicationScope,分别对应JSP中的pageContext、request、session和application对象。这些范围用于存储和检索数据。 **二...
USERNAME:${sessionScope['SPRING_SECURITY_LAST_USERNAME']}" /> PASSWORD:<input type="password" name="j_password" value="" /><br/> ``` 通过以上步骤,我们便可以成功地配置和使用 Spring Security...
${requestScope.msg} ${sessionScope.msg2} JAVA: ModelAndView ModelMap Model里添加的参数 JSP: 直接用${参数名} JAVA: 前台表单里的信息,或者是直接在url后面以?name=value&name2=value2形式传到后台的 JSP...
EL 中的隐含对象有四个:pageScope、requestScope、sessionScope 和 applicationScope,它们基本上就和 JSP 的 pageContext、request、session 和 application 一样。在 EL 中,这四个隐含对象只能用来取得范围属性...
EL 中提供了四个与范围有关的隐含对象:pageScope、requestScope、sessionScope 和 applicationScope。这些对象可以用于取得范围属性值。 与输入有关的隐含对象 EL 中提供了两个与输入有关的隐含对象:param 和 ...
EL 访问作用域包括 pageScope、requestScope、sessionScope 和 applicationScope。pageScope 主要用于获取页面范围内的属性值,requestScope 主要用于获取请求范围内的属性值,sessionScope 主要用于获取会话范围内...
EL允许开发者从各种作用域(如pageScope、requestScope、sessionScope和applicationScope)中轻松地获取和操作数据,而无需进行繁琐的类型转换。在JSTL 1.1及以后的版本中,EL成为JSP 2.0规范的一部分,可以在JSP...
Spring框架的核心特性包括依赖注入(Dependency Injection, DI)、面向切面编程(Aspect-Oriented Programming, AOP)、数据访问/集成(Data Access / Integration)等,这些特性使得开发者能够更加高效地开发、测试...
如果直接写`${hello}`,则EL会从最小的作用域开始查找,依次为`pageScope`、`requestScope`、`sessionScope`和`applicationScope`,直到找到对应的值为止。 #### 实例详解 接下来,我们将通过几个具体的示例来...
首先,我们需要理解Spring Web Flow的核心概念,包括`Flow`、`State`和`Transition`。`Flow`代表了一个完整的业务流程,比如购物车结账流程;`State`则是流程中的各个步骤,如选择商品、确认订单等;`Transition`则...
这些范围对应于JSTL中的PageScope、RequestScope、SessionScope和ApplicationScope。可以显式指定范围,例如`${sessionScope.username}`。 EL的另一个重要特性是自动类型转换。在表达式`${param.count + 20}`中,...
同时,为了使Spring MVC能够与Hibernate一起工作,我们需要在实体类上添加@Entity注解,创建对应的表,并使用@SessionScope或@Service注解标记服务层的类,以便Spring管理。 在项目运行过程中,Test6可能是测试类...
domino xapges 开发sessionScope