Bean的作用域
Spring容器创建的Bean默认是单例的。Spring容器调用配置方法完成Bean的创建之后,Bean就缓存在Spring容器里。之后每次调用同一配置方法创建Bean,Spring容器只会返回缓存在Spring容器里的Bean,不再创建新的Bean。这意味着同一配置方法在同一Spring容器里无论被调用了多少次,都只会返回同一实例的Bean。因此,Spring容器创建的Bean默认是单例的。同时我们也应注意到,这里的单例与单例设计模式里的单例是有区别的,不能混为一谈。单例设计模式里的单例指的是类的实例由类的加载器方法创建,无论类的加载器方法被调用了多少次,都只会返回同一实例。
在Web开发中,我们通常只需创建单例的Bean。因为诸如控制器之类的Bean是无状态的。无论哪个用户发来请求,都能使用同一控制器实例处理,根本就不需要再创建新的控制器实例。然而对于一些类,比如数据模型类,每个请求所产生或获取的数据都是不一样的。这意味着这样的类是有状态的。把这些有状态的类创建为单例的显然不妥。作为替代,我们通常选择创建这些类的域对象(Domain Object),通过new关键字在Bean的方法中创建这些类的实例。因此,在Web开发中,我们往往只需告诉Spring容器创建单例的Bean
然而,在某些罕见的应用场景中,我们可能需要创建非单例的Bean。这意味着除了单例(Singleton)作用域之外,Spring容器还需支持创建具有其它作用域的Bean。具体如下:
1.原型(Prototype):Spring容器每次调用配置方法创建Bean时都会重新创建Bean的实例,调用几次就创建几个实例。
2.请求(Request):请求指的是Web请求,只有Web相关的Spring容器(比如XmlWebApplicationContext)才支持请求作用域。指定作用域为请求后,同一配置方法在同一Web请求里无论被调用了多少次,都只会创建一个Bean的实例。
3.会话(Session):会话指的是Web会话,只有Web相关的Spring容器(比如XmlWebApplicationContext)才支持会话作用域。指定作用域为会话后,同一配置方法在同一Web会话里无论被调用了多少次,都只会创建一个Bean的实例。
Bean的作用域可由@Scope注解配置。@Scope注解有个String类型的value属性。我们可把singleton(单例),prototype(原型),request(请求)或session(会话)这些字符串指给@Scope注解,告诉Spring容器创建具有相应作用域的Bean。如下所示:
1 @Bean("music") 2 @Scope(value="singleton") 3 public Music produceMusic() { 4 return new Music("Dream"); 5 }