参考文献

作用域

来源 说明
singleton 默认 Spring Bean 作用域,一个 BeanFactory 有且仅有一个实例
prototype 原型作用域,每次依赖查找和依赖注入生成新 Bean 对象
request 将 Spring Bean 存储在 ServletRequest 上下文中; Only valid in the context of a web-aware Spring ApplicationContext.
session 将 Spring Bean 存储在 HttpSession 中 ; Only valid in the context of a web-aware Spring ApplicationContext.
application 将 Spring Bean 存储在 ServletContext 中; Only valid in the context of a web-aware Spring ApplicationContext.
websocket 将 Spring Bean 存储在 WebSocket 中; Only valid in the context of a web-aware Spring ApplicationContext.

Singleton Bean 作用域

img

  • 注意事项: 单例Bean是整个应用共享的,使用时需要考虑线程安全问题.

prototype Bean 作用域

img

1
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
  • 注意事项
    • Spring 容器没有办法管理Prototype Bean的完整生命周期,也没有办法记录示例的存在.销毁回调方法将不会执行,可以利用 BeanPostProcessor 进行清扫工作.
    • 多例Bean每次获取的时候都会重新创建,如果这个Bean比较复杂,创建时间较长,会影响系统的性能.

request、session、applicationBean作用域

  • request、session、application都是在Spring Web容器环境中才会有的

request Bean作用域

  • 当一个bean的作用域为request,表示在一次http请求中,一个bean对应一个实例;对每个http请求都会创建一个bean实例,request结束的时候,这个bean也就结束了

  • 配置

    • XML:<bean id="loginAction" class="com.something.LoginAction" scope="request"/>

    • Java注解

      • @RequestScope
      • @Scope(WebApplicationContext.SCOPE_REQUEST)

session Bean作用域

  • 配置
    • XML: <bean id="userPreferences" class="com.something.UserPreferences" scope="session"/>
    • Java注解
      • @SessionScope
      • @Scope(WebApplicationContext.SCOPE_SESSION)

application Bean作用域

  • 配置
    • XML: <bean id="appPreferences" class="com.something.AppPreferences" scope="application"/>
    • Java注解
      • @ApplicationScope
      • @Scope(WebApplicationContext.SCOPE_APPLICATION)

自定义Bean作用域

  • 实现Scope

    • org.springframework.beans.factory.config.Scope

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      package org.springframework.beans.factory.config;

      import org.springframework.beans.factory.ObjectFactory;
      import org.springframework.lang.Nullable;


      public interface Scope {

         /**
         * 返回当前作用域中name对应的bean对象
         * name:需要检索的bean的名称
         * objectFactory:如果name对应的bean在当前作用域中没有找到,那么可以调用这个ObjectFactory来创建这个对象
         **/
      Object get(String name, ObjectFactory<?> objectFactory);

      /**
      * 将name对应的bean从当前作用域中移除
      **/
      @Nullable
      Object remove(String name);

      /**
      * 用于注册销毁回调,如果想要销毁相应的对象,则由Spring容器注册相应的销毁回调,而由自定义作
      用域选择是不是要销毁相应的对象
      */
      void registerDestructionCallback(String name, Runnable callback);

      /**
      * 用于解析相应的上下文数据,比如request作用域将返回request中的属性。
      */
      @Nullable
      Object resolveContextualObject(String key);

      /**
      * 作用域的会话标识,比如session作用域将是sessionId
      */
      @Nullable
      String getConversationId();
      }
  • 注册Scope

    • API: org.springframework.beans.factory.config.ConfigurableBeanFactory#registerScope

    • XML配置:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      <?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"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      https://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/aop
      https://www.springframework.org/schema/aop/spring-aop.xsd">

      <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
      <property name="scopes">
      <map>
      <entry key="thread">
      <bean class="org.springframework.context.support.SimpleThreadScope"/>
      </entry>
      </map>
      </property>
      </bean>

      <bean id="thing2" class="x.y.Thing2" scope="thread">
      <property name="name" value="Rick"/>
      <aop:scoped-proxy/>
      </bean>

      <bean id="thing1" class="x.y.Thing1">
      <property name="thing2" ref="thing2"/>
      </bean>

      </beans>