作用域素名称 | 说明 |
---|---|
singleton ( 单例 ) | 使用 singleton 定义的 Bean Spring 容器中将只有一个实例,也就是说,无论有多少个 Bean 引用它,始终将指向同一个对象。这也是 Spring 容器默认的作用域 |
prototype ( 原型 ) | 每次通过 Spring 容器获取的 prototype 定义的 Bean 时,容器都将创建一个新的 Bean 实例 |
request | 在一次 HTTP 请求中,容器会返回该 Bean 的同一个实例。对不同的 HTTP 请求则会产生一个新的 Bean ,而且该 Bean 仅在当前 HTTP Request 内奇效 |
session | 在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例 对不同的 HTTP 需求则会产生一个新的 Bean ,而且该 Bean 仅在当前 HTTP Session内奇效 |
globalSession | 在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例,仅在使用 portlet 上下文时有效 |
application | 为每个 ServletContext 对象创建一个实例。仅在 Web 相关的 ApplicationContext 中生效 |
websocket | 为每个 websocket 对象创建一个实例。仅在 Web 相关的 ApplicationContext 中生效 |
1. singleton ( 单例 )
如果bean的作用域的属性被声明为singleton,那么Spring Ioc容器只会创建一个共享的bean实例。对于所有的bean请求,只要id与该bean定义的相匹配,那么Spring在每次需要时都返回同一个bean实例。
Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,singleton作用域是Spring中的缺省作用域。你可以在 bean 的配置文件中设置作用域的属性为 singleton,如下所示:
<!-- applicationContext.xml -->
<!-- A bean definition with singleton scope -->
<bean id="userDao" class="dao.impl.UserDaoImpl" scope="singleton">
<!-- collaborators and configuration for this bean go here -->
</bean>
测试类
// TestSpring.java
public class TestSpring {
/**
* Bean的作用域:singleton(单例)测试
*/
@Test
public void TestSingleton() {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao1 = (UserDao) app.getBean("userDao");
UserDao userDao2 = (UserDao) app.getBean("userDao");
System.out.println(userDao1);
System.out.println(userDao2);
}
}
运行结果
MySpring.dao.Impl.UserDaoImpl@6adede5
MySpring.dao.Impl.UserDaoImpl@6adede5
2. prototype ( 原型 )
当一个bean的作用域为prototype,表示一个bean定义对应多个对象实例。声明为prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。
prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。
还是上面的代码。其他代码不变,把Bean.xml文件中bean的作用域由singleton改为prototype。
<!-- applicationContext.xml -->
<!-- A bean definition with prototype scope -->
<bean id="userDao" class="dao.impl.UserDaoImpl" scope="prototype">
<!-- collaborators and configuration for this bean go here -->
</bean>
测试类
// TestSpring.java
public class TestSpring {
/**
* Bean的作用域:prototype(原型)测试
*/
@Test
public void TestPrototype() {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao1 = (UserDao) app.getBean("userDao");
UserDao userDao2 = (UserDao) app.getBean("userDao");
System.out.println(userDao1);
System.out.println(userDao2);
}
}
运行结果
MySpring.dao.Impl.UserDaoImpl@25bbe1b6
MySpring.dao.Impl.UserDaoImpl@5702b3b1
3. 使用注解定义 bean 的作用域。
除了在Bean.xml文件中定义bean的作用域之外,还可以使用注解来定义 bean 的作用域。
- 在Bean中加上注解。
// UserDaoImpl.java
@Component("userDao")
@Scope("prototype")
public class UserDaoImpl implements UserDao {
public void save(){
System.out.println("save running...");
}
}
@Component(“userDao”) 注解是告诉Spring这是一个bean,即id=“userDao”
@Scope(“prototype”) 注解是告诉Spring该bean的作用域是prototype,即socpe=“prototype”
- 修改applicationContext.xml配置文件
在applicationContext.xml配置文件中添加第三方约束:
- 命名空间:
xmlns:context="http://www.springframework.org/schema/context"
- 约束路径:
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
<!-- applicationContext.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描MySpring.dao.Impl.UserDaoImpl包中的所有类的注解。 -->
<context:component-scan base-package="dao.impl.UserDaoImpl"></context:component-scan>
</beans>
<context:component-scan base-package=“dao.impl.UserDaoImpl”></context:component-scan>就是扫描MySpring.dao.Impl.UserDaoImpl包中的所有类的注解。