介绍:
Spring核心容器实例化bean并管理其生命周期。 在定义bean时,我们可以提供其范围。 除非明确提供,否则单例是Spring容器中bean的默认范围。
Spring提供了五种类型的bean作用域。 在本教程中,我们将探讨它们中的每一个。
1.
单例作用域可确保每个Spring IoC容器仅存在该bean的一个实例。 该单个Bean实例存储在所有单个Bean的缓存中,并为每个后续请求返回对此缓存对象的引用。
众所周知,默认情况下,所有Spring bean都是单例的。
假设我们有一个Student bean:
@Component
public class Student {
private int id;
private String name;
//constructor, getters, setters
}
默认情况下, Student类将是单例bean。 让我们尝试将其加载到我们的main()方法中:
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("appContext.xml");
Student student1 = (Student) context.getBean("student");
student1.setName("John");
System.out.println(student1.getName()); //Prints 'John'
Student student2 = (Student) context.getBean("student");
System.out.println(student2.getName()); //Prints 'John'
}
}
显然,已经为第二次调用返回了Student Bean的现有实例。 换句话说, student1和student2引用都指向同一对象。
2.
对于原型范围内的bean,将在我们的应用程序代码中为该特定bean的每个请求创建一个新实例。
我们可以使用@Scope批注将bean的范围配置为原型:
@Component
@Scope("prototype")
public class Student {
...
}
或使用基于XML的配置时,我们将:
<bean id = "student" class="org.programmergirl.domain.Student"
scope="prototype">
</bean>
现在,让我们看看在main()方法中会发生什么:
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("appContext.xml");
Student student1 = (Student) context.getBean("student");
student1.setName("John");
System.out.println(student1.getName()); //Prints 'John'
Student student2 = (Student) context.getBean("student");
System.out.println(student2.getName()); //Prints null
}
}
这里, student2引用Student类的新实例,其名称属性为null 。
注意,我们应该始终对有状态bean使用原型作用域,对无状态bean使用单例作用域。
3.
使用请求范围时,将为每个HTTP请求创建一个新实例。 HTTP请求完成时,该bean实例将被销毁。
我们可以使用注释配置请求范围:
@Component
@Scope("request")
public class Student {
...
}
//Or
@Component
@RequestScope
public class Student {
...
}
或通过XML配置:
<bean id = "student" class="org.programmergirl.domain.Student"
scope="request">
</bean>
4.
对于会话范围,Spring容器为每个HTTP会话创建一个新的bean实例。 HTTP会话中的所有HTTP请求将共享相同的bean实例。
要配置会话范围的Bean,我们将使用:
@Component
@Scope("session")
public class Student {
...
}
//Or
@Component
@SessionScope
public class Student {
...
}
对于基于xml的配置,我们将有:
<bean id = "student" class="org.programmergirl.domain.Student"
scope="session">
</bean>
当HTTP会话关闭时,容器将销毁会话范围的Bean实例。
5.
在应用程序范围内,可感知Web的容器会根据ServletContext创建一个bean实例。 请注意,应用程序范围不同于单例范围:
- 我们可以在独立应用程序中使用单例作用域。 该应用程序范围仅对基于Web的Spring容器/应用程序有效
- 对于单例作用域,每个应用程序上下文存在一个实例。 另一方面,应用程序范围的Bean对于整个ServletContext具有单个实例。 我们可能有多个应用程序共享同一个ServletContext
让我们将Student bean配置为应用程序范围的bean:
@Component
@Scope("application")
public class Student {
...
}
//Or
@Component
@ApplicationScope
public class Student {
...
}
基于xml的定义如下所示:
<bean id = "student" class="org.programmergirl.domain.Student"
scope="application">
</bean>
结论:
在本教程中,我们探索了各种Spring bean范围。
请注意,请求,会话和应用程序bean范围仅对可感知网络的Spring ApplicationContext有效。
翻译自: https://www.javacodegeeks.com/2019/06/spring-bean-scopes.html