Bean 定义
bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的。
Spring 配置元数据
Spring IoC 容器完全由实际编写的配置元数据的格式解耦。有下面三个重要的方法把配置元数据提供给 Spring 容器:
- 基于 XML 的配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 全参构造,使用成员属性索引对应 --> <bean id="userOnIndex" class="intron.spring.entity.User"> <constructor-arg index="0" value="张三"></constructor-arg> <constructor-arg index="1" value="18"></constructor-arg> </bean> <!-- 全参构造,使用成员属性类型对应 --> <bean id="userOnType" class="intron.spring.entity.User"> <constructor-arg type="java.lang.String" value="张三"></constructor-arg> <constructor-arg type="int" value="18"></constructor-arg> </bean> </beans>
- 基于注解的配置
@Repository public class JpaMovieFinder implements MovieFinder { // implementation elided for clarity } @Service public class SimpleMovieLister { private MovieFinder movieFinder; public SimpleMovieLister(MovieFinder movieFinder) { this.movieFinder = movieFinder; } }
- 基于 Java 的配置
@Configuration public class BeanConfiguration { @Bean public Account account(){ return new Account("001001001"); } @Bean public User user(Account account){ return new User("张三",18,account); } @Bean public User userNoAccount(){ return new User("张三",18,null); } }
Bean 的作用域
当在 Spring 中定义一个 bean 时,你必须声明该 bean 的作用域的选项。例如,为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean 的作用域的属性为 prototype。同理,如果你想让 Spring 在每次需要时都返回同一个bean实例,你应该声明 bean 的作用域的属性为 singleton。
Spring 框架支持以下五个作用域,分别为 singleton、prototype、request、session 和 global session,5种作用域说明如下所示,
singleton:单例模式(多线程下不安全)
- singleton:单例模式,Spring IoC 容器中只会存在一个共享的 Bean 实例,无论有多少个Bean 引用它,始终指向同一对象。该模式在多线程下是不安全的。Singleton 作用域是Spring 中的缺省作用域,也可以显示的将 Bean 定义为 singleton 模式,配置为:
prototype:原型模式每次使用时创建
- prototype:原型模式,每次通过 Spring 容器获取 prototype 定义的 bean 时,容器都将创建一个新的 Bean 实例,每个 Bean 实例都有自己的属性和状态,而 singleton 全局只有一个对象。根据经验,对有状态的bean使用prototype作用域,而对无状态的bean使用singleton作用域。
Request:一次 request 一个实例
- request:在一次 Http 请求中,容器会返回该 Bean 的同一实例。而对不同的 Http 请求则会产生新的 Bean,而且该 bean 仅在当前 Http Request 内有效,当前 Http 请求结束,该 bean实例也将会被销毁。
session
- session:在一次 Http Session 中,容器会返回该 Bean 的同一实例。而对不同的 Session 请求则会创建新的实例,该 bean 实例仅在当前 Session 内有效。同 Http 请求相同,每一次session 请求创建新的实例,而不同的实例之间不共享属性,且实例仅在自己的 session 请求内有效,请求结束,则实例将被销毁。
global Session
- global Session:在一个全局的 Http Session 中,容器会返回该 Bean 的同一个实例,仅在使用 portlet context 时有效。
总结
Spring IOC容器创建一个Bean实例时,可以为Bean指定实例的作用域,作用域包括singleton(单例模式)、prototype(原型模式)、request(HTTP请求)、session(会话)、global-session(全局会话)。
singleton和prototype模式这两个模式的作用域在Spring框架中是经常用到的。对于singleton作用域的Bean,IOC容器每次都返回同一个实例,而prototype作用域的Bean,IOC容器每次产生一个新的实例。
配置Bean为singleton作用域的配置代码如下。
<bean id="person" class="com.mengma.scope.Person" scope="singleton"/>
配置Bean为prototype作用域的配置代码如下。
<bean id="person" class="com.mengma.scope.Person" scope="prototype"/>
\