• Bean的作用域



    默认情况下,Spring应用上下文中所有bean都是作为以单例(singleton)的形式创建的。

    • 单例(Singleton): 在整个应用中,只创建bean的一个实例
    • 原型(Prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例
    • 会话(Session):在Web应用中,为每个会话创建一个bean实例
    • 请求(Request):在Web应用中,为每个请求创建一个bean实例

    推荐使用方式

    @Component
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public class Notepad(.....)
    
    当然使用
    @Scope("prototype")也是可以的,但是推荐使用常量
    
    xml配置
    <bean id = "notepad" class = "com.lyc.Notepad" scope="prototype"/>

    使用会话和请求作用域

       在web应用中,single和prototype不太适合使用,相反 session和required的会比较合适。例如,在典型的电子商务应用中,可能会有一个bean代表用户的购物车。如果购物车是单例的话,那么将会导致所有的用户都会向同一个购物车中添加商品。另一方面,如果购物车是原型作用域(prototype),那么在应用中某一个地方往购物车中添加商品,在应用的另外一个地方可能就不可用了,因为在这里注入的是另外一个原型作用域的购物车。

          就购物车bean来说,会话作用域是最合适的,因为它与给定的用户关联性最大。要指定会话的作用域,我们可以使用@scope注解,它的使用方式与指定原型作用域是相同的

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

      这里,我们将value设置为WebApplicationContext中的SCOPE_SESSION常量(它的值是session)。这会告诉spring为web应用中的每个会话创建一个ShoppingCart。这会创建多个ShoppingCart bean实例,但是对于给定的会话只会创建一个实例,在当前会话操作中,这个bean实际上相当于单例

      注意: @Scope同时还有一个ProxyMode,他被设置成了ScopedProxyMode.INTERFACES.这个属性解决了将会话或请求作用域的bean注入到单例bean中所遇到的问题。

      假设我们要将ShoppingCart bean注入到单例StoreService bean 的setter方法中,如下所示:

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

      因为StoreService是一个单例的bean,会在Spring应用上下文加载的时候创建。当它创建的时候,Spring会试图将ShoppingCart bean注入到setShoppingCart()方法中。但是ShoppingCart bean是会话作用域的,此时并不存在。直到某个用户进入系统,创建了会话之后,才会出现ShoppingCart实例。
      另外,系统中将会有多个ShoppingCart实例;每隔用户一个。我们并不想让Spring注入某个固定的ShoppingCart实例到StoreService中。我们希望的是当StoreService处理购物车功能时,它所使用的ShoppingCart实例恰好是当前会话所对应的那一个。
      Spring并不会将实际的ShoppingCart bean注入到StoreService中,Spring会注入一个到ShoppingCart bean的代理,这个代理会暴露与ShoppingCart相同的方法,所以StoreService会认为它就是一个购物车。但是当StoreService调用ShoppingCart的方法时,代理会对其进行懒解析并将调用委托给会话作用域内真正的ShoppingCart bean。

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Scope {
        @AliasFor("scopeName")
        String value() default "";
    
        @AliasFor("value")
        String scopeName() default "";
    
        ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
    }
    //  ScopedProxyMode 是一个枚举类
     public enum ScopedProxyMode {
        DEFAULT,
        NO,
        INTERFACES,
        TARGET_CLASS;
    
        private ScopedProxyMode() {
        }
    }

      如果ShoppingCart是接口而不是类的话,proxyMode属性被设置成ScopeProxyMode.INTERFACES,表明这个代理要实现ShoppingCart接口,并将调用委托给实现bean
      如果ShoppingCart是一个具体的类,那么ProxyMode属性就设置为ScopedProxyMode.TARGET_CLASS,用来表明要以生成目标类扩展的方法创建代理

  • 相关阅读:
    putty远程登录,no supported authentication methods available解决方法(腾讯云)
    spring boot 集成 springbootstarterquartz 集群版配置
    排序算法
    密码发生器
    分解质因数
    python基础面试题
    计算输入密码的时间
    论文解读(GCC)《Efficient Graph Convolution for Joint Node RepresentationLearning and Clustering》 Learner
    期望、方差、协方差 Learner
    论文解读(LGAE)《Simple and Effective Graph Autoencoders with OneHop Linear Models》 Learner
  • 原文地址:https://www.cnblogs.com/zhuguangzhe/p/12673872.html
Copyright © 2020-2023  润新知