bean的作用域

加紧学习,抓住中心,宁精勿杂,宁专勿多。  ——***

Spring作用域

  在默认情况下,Spring上下文中所有bean都是作为以单例(singleton)的形式创建的。有时候,你所使用的类是易变(mutable),在这种情况下将bean声明为单例是不安全的。

  Spring定义了多种作用域,可以基于这些作用域创建bean,包括:

  1) 单例(Singleton):在整个应用中,只创建bean的一个实例。

  2) 原型(Prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。

  3) 会话(Session):在Web应用中,为每个会话创建一个bean实例。

  4) 请求(Request):在Web应用中,为每个请求创建一个bean 实例。

 

设置原型作用域(Prototype)

  1.在Java配置中使用@Scope注解,它可以与@Component或@Bean一起使用。

package chapter3.practice4;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Ball {
    /**
     * @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 等同于  @Scope("prototype")
     * @Scope(ConfigurableBeanFactory.) 等同于  @Scope("prototype")
     */
}
package chapter3.practice4;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class BallConfig {
    
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Ball ball() {
        return new Ball();
    }
}

  2.在XML配置中,可以通过<bean>元素的scope属性*设置作用域。

<?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:c="http://www.springframework.org/schema/c"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc 
   http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd"
> <bean scope="prototype" id="ball" class="chapter3.practice4.Ball"></bean> </beans>

 

使用会话和请求作用域

  1.在Web应用中,如果能够实例化在会话和请求范围内共享的bean,是非常有意义的。在典型的电子商务中,购物车bean指定会话作用域是最为合适的,因为它与给定用户关联性最大。如下,在Java配置中可以使用@Scope注解指定会话作用域:

package chapter3.practice4;

import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;

@Component
@Scope(
        value = WebApplicationContext.SCOPE_SESSION,
        proxyMode = ScopedProxyMode.INTERFACES
)
public class ShoppingCart {

}

  1) value属性设置为WebApplicationContext.SCOPE_SESSION(Session),它会告诉Spring为Web应用中每个会话创建一个ShoppingCart实例,在当前会话中,这个ShoppingCart实例实际上相当于单例的。

  2) proxyMode属性设置为ScopedProxyMode.INTERFACES,这个属性解决了将会话或请求作用域的bean注入到单例bean中所遇到的问题:

package chapter3.practice4;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class ShopService {
    
    private ShoppingCart shoppingCart;
    
    @Autowired
    public void setShoppingCart(ShoppingCart shoppingCart) {
        this.shoppingCart = shoppingCart;
    }
    
    
}

  ①  ShopService bean的作用域默认是单例,会在Spring应用上下文加载的时候创建。当它创建的时候,Spring会试图将ShoppingCart bean注入到setShoppingCart()方法中,但是ShoppingCart作用域是会话域,此时并没有创建,只有当某个用户进入系统,创建了会话之后,才会创建ShoppingCart bean。

  ② 系统中有多个用户,每个用户都将会有一个ShoppingCart实例,我们不想注入某个固定的ShoppingCart实例到ShopService中,而是希望注入的ShoppingCart实例恰好就是当前会话的实例。

  设定@Scope的proxyMode属性后,Spring不会将实际的ShoppingCart实例注入到ShopService,而是注入一个ShoppingCart实例的代理,当ShopService调用ShoppingCart的方法时,代理会对其进行懒解析并将调用委托给会话作用域内真正的ShoppingCart实例。

  代理模式有两种:

  (1) 基于接口的代理(ScopedProxyMode.INTERFACES),即ShoppingCart是接口,Spring就会创建基于接口的代理。

  (2) 基于类的代理(ScopedProxyMode.TARGET_CLASS),即ShoppingCart是一个具体的类,Spring会使用CGLib*生成基于类的代理。

  

  2.在XML中声明会话或请求作用域的bean,设置<bean>元素的scope属性;要设置代理模式,使用Spring aop命名空间的一个新元素:<aop:scoped-proxy>元素。

<?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:c="http://www.springframework.org/schema/c"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc 
http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd"
> <bean id="cart" class="chapter3.practice4.ShoppingCart" scope="session"> <aop:scoped-proxy/> </bean> </beans>

  值得注意的是:<aop:scoped-proxy>默认的代理模式是基于类的代理,若想生成基于接口的代理,则需设置<aop:scoped-proxy>元素的proxy-target-classs属性为false。

<?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:c="http://www.springframework.org/schema/c"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc 
http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd"
> <bean id="cart" class="chapter3.practice4.ShoppingCart" scope="session"> <aop:scoped-proxy proxy-target-class="false" /> </bean> </beans>

 

posted @ 2018-04-13 00:06  学而时习之,不亦说乎?  阅读(867)  评论(0编辑  收藏  举报