spring-基础三
前言
创建一个bean的定义时候,可以创建一个模版(recipe)通过bean定义的类定义去创建一个真实的实例。bean定义是模版(recipe)的概念很重要,因为这意味着,与使用类一样,可以从一个模版(recipe)创建多个对象实例.我们不仅可以控制要插入到从特定bean定义创建的对象中的各种依赖项和配置值,还可以控制从特定bean定义创建的对象的作用域。这种方法是非常有用的和灵活的,因为可以选择通过配置创建的对象的作用域,而不必在Java类级别上考虑对象的作用域。bean能够定义部署到一个或多个作用域。
Bean Scopes
创建一个bean定义,其实质是用该bean定义对应的类来创建真正实例的“配方”。把bean定义看成一个配方很有意义,它与class很类似,只根据一张“处方”就可以创建多个实例。不仅可以控制注入到对象中的各种依赖和配置值,还可以控制该对象的作用域。这样可以灵活选择所建对象的作用域,而不必在Java Class级定义作用域。Spring Framework支持六种作用域.
singleton
在Spring Ioc 容器中只会存在一个共享的bean实例,我们获取到的实例都是同一实例,Spring 默认的创建实例方式就是单例模式,但是该单例模式与平时所说的单例模式又有所不同,平时所使用的单例是针对JVM来说的,Spring的单例模式是针对容器来所,就是说同一个Spring Ioc容器中只有一个实例.该作用域创建方式:
方式一:
<bean id="bean" class="com.panic.test.other.springtest.BeanA" scope="singleton">
<property name="name" value="测试类"/>
</bean>
指定scope为sigleton,spring 默认创建方式可以缺省指定
方式二:
@Scope("singleton")
public class BeanA {
}
通过注解指定,显示指定bean的作用范围
官网解释:
prototype
当一个bean的作用域为原型模式,表示一个bean对应多个实例对象,每次获取bean(将bean注入到另一个容器或者通过getBean()方式获取)都会创建一个新的bean实例,当初始化容器时我们并没有实例化bean而是在使用时进行实例化,这种模式下,配置销毁生命周期回调是无效的,就是说我们使用这种模式创建了实体,需要我们自己释放实体所占用的资源,该实体的生命周期由我们自己管理,Spring Ioc不再管理该实体的生命周期,设置prototype类型实体方式:
方式一:
<bean id="bean" class="com.panic.test.other.springtest.BeanA" scope="prototype">
<property name="name" value="测试类"/>
</bean>
或者
<bean id="bean" class="com.panic.test.other.springtest.BeanA" singleton="false">
<property name="name" value="测试类"/>
</bean>
指定singleton为false时就会设置为prototype类型
方式二:
@Scope("prototype")
@Component
public class BeanA {
}
官网解释:
request
request模式是针对web程序来说的,每一次http请求都会新创建一个实体,该实体仅在当前http request 请求类有效,当请求结束后该实体的生命周期也结束了.创建方式:
方式一:
<bean id="bean" class="com.panic.test.other.springtest.BeanA" scope="request">
<property name="name" value="测试类"/>
</bean>
方式二:
@RequestScope
@Component
public class BeanA {
}
session
与request模式相同该模式也只针对与web程序,每一次http请求都会创建同一个实体,该实体的生命周期跟随该http session 的生命周期,在该http session 生命周期类更改实体属性其他http session是无法感知的.创建方式:
request模式是针对web程序来说的,每一次http请求都会新创建一个实体,该实体仅在当前http request 请求类有效,当请求结束后该实体的生命周期也结束了.创建方式:
方式一:
<bean id="bean" class="com.panic.test.other.springtest.BeanA" scope="session">
<property name="name" value="测试类"/>
</bean>
方式二:
@SessionScope
@Component
public class BeanA {
}
Application
Spring容器通过使用appPreferences的bean定义为整个Web应用创建一个AppPreferences的bean新实例。也就是说,appPreferences的作用域在ServletContext级别并且作为一个常规的ServletContext属性被储存。这个和Spring的单例bean类似,但有两个重要的区别:每个ServletContext是一个单例,而不是每个Spring的ApplicationContext(在给定的Web应用程序中可能有多个),并且它实际上是暴露的,因此作为ServletContext属性可见。创建方式:
方式一:
<bean id="bean" class="com.panic.test.other.springtest.BeanA" scope="application">
<property name="name" value="测试类"/>
</bean>
方式二:
@ApplicationScope
@Component
public class BeanA {
}
WebSocket
将单个bean定义限制在WebSocket生命周期。仅在Spring ApplicationContext Web容器有效,该模式下创建的实体,其生命周期依赖与 websocket 生命周期,当websocket实例被销毁时,其说拥有的bean将会被回收,websocket范围内的bean通常是单例的,并且比任何单独的WebSocket会话寿命更长。
方式一:
<bean id="bean" class="com.panic.test.other.springtest.BeanA" scope="websocket">
<property name="name" value="测试类"/>
</bean>
方式二:
@Component
@Scope("websocket")
public class BeanA {
}
注意事项
singleton bean 与 prototype bean依赖
当你使用依赖于原型bean的单例作用域bean时(单例引用原型bean),需要注意的是这些依赖项在初始化时候被解析。因此,如果你依赖注入一个原型bean到一个单例bean中,一个新原型bean被初始化并且依赖注入到一个单例bean。原型实例是唯一一个被提供给单例作用域bean的实例。换而言之:单例bean引用原型bean时原型bean只会有一个,也就是原型bean被单例化.
然而,假设你希望单例作用域bean在运行时重复获取原型作用域bean的一个新实例。你不能依赖注入一个原型bean到一个单例bean,因为注入只发生一次,当Spring容器实例化单例bean、解析和注入它的依赖时。如果在运行时不止一次需要原型bean的新实例,这个时候就要使用方法注入的方式注入bean.
Request, Session, Application, and WebSocket Scopes
这四种作用域是针对web程序来说的,也就是当我们使用Spring的ApplicationContext时才能使用这四种作用域模式,如果我们将这些作用域与常规的Spring IoC容器 比如:ClassPathXmlApplicationContext 一起使用时会抛出IllegalStateException异常,说明bean是未知的作用域.