Spring框架之Bean Scope

开发 架构
Spring容器默认的作用域,只有一个共享的单例bean实例被管理,id与bean定义的id匹配的bean请求,spring容器都会返回一个特定的bean实例。

Spring框架支持六个作用域,其中四个只有在使用web感知的ApplicationContext时才可用。

Spring支持以下6中bean scopes:

  • singleton:单例模式(默认值),在Spring容器中只会创建一个实例。
  • prototype:原型模式,每次通过Spring容器获取bean时,容器都会新建一个实例。
  • request:每次HTTP请求都会创建一个实例,但只在http request范围有效。
  • session:​在http session生命周期内,共享一个实例,不同session有不同的实例。
  • application:在ServletContext生命周期内,只有一个实例。
  • webSocket:在webSocket范围内只有一个实例。

Singleton scope

Spring容器默认的作用域,只有一个共享的单例bean实例被管理,id与bean定义的id匹配的bean请求,spring容器都会返回一个特定的bean实例。换句话说,当您定义一个bean为单例时,Spring IoC容器只会创建该bean的一个实例。这个实例存储在缓存中,所有后续对这个bean的请求和引用都返回缓存对象。

基于java configuration方式定义一个singleton的bean

@Configuration
public class AppConfiguration {
@Bean
@Scope("singleton") // default scope
public UserService userService(){
return new UserService();
}
}

prototype scope

原型模式会导致每次请求都会创新一个新的bean实例,就是说当一个bean被注入到另一个bean中,或者通过getBean()方法调用请求它时会新创建一个bean实例。通常,有状态的bean使用prototype scope,无状态的bean使用singleton scope。与其它scope不同,spring容器不管理原型scope的整个生命周期,容器实例化、配置和以其他方式组装原型对象,都将其交给client,而无需进一步记录该原型实例。

基于java configuration方式定义一个prototype的bean

@Configuration
public class AppConfiguration {
@Bean
@Scope("prototype")
public UserService userService(){
return new UserService();
}
}

具有原型bean依赖项的单例bean

当您将单例bean与原型bean的依赖项一起使用时,请注意,依赖项是在实例化时解析的。因此,如果依赖项将原型注入到单例bean中,则会实例化一个新的原型bean,然后将依赖项注入到单例bean中。原型实例是唯一一个提供给单例bean的实例。

Request、Session、Application和WebSocket作用域

Request、Session、Application、WebSocket作用域仅在使用web感知的Spring ApplicationContext实现(如XmlWebApplicationContext)时可用。如果将这些作用域与常规Spring IoC容器(如ClassPathXmlApplicationContext)一起使用,则会抛出一个IllegalStateException,未知bean作用域。

鉴于目前技术发展采用前后端分离模式开发,已很少单独使用Spring web mvc模式,此处不在讲述这四个作用域,大家可以参考官方文档了解。

InitializingBean和DisposableBean

在Spring中,为了与容器bean的生命周期管理进行交互,可以实现InitializingBean和DisposableBean接口。容器初始化时执行AfterPropertieSet(),销毁是调用destroy(),以便bean在初始化和销毁bean时执行某些操作。

@PostConstruct和@PreDestroy注释通常被认为是新版Spring应用程序中接收生命周期回调的最佳实践。使用这些注释意味着您的bean没有耦合到特定于Spring的接口。

  1. 实现InitializingBean接口,在所有bean设置完properties后将运行afterPropertiesSet()。
  2. 实现DisposableBean接口,在Spring容器释放bean后运行destroy()。

InitializingBean和DisposableBean示例

在本例中,我们将使用afterPropertiesSet()方法在应用程序启动期间使用用户对象填充内存中的列表数据结构。我们还将在应用程序关闭期间使用destroy()方法从列表中删除用户对象。

package com.demo.spring;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class DatabaseInitiaizer implements InitializingBean, DisposableBean {
private List < User > listOfUsers = new ArrayList < > ();
@Override
public void afterPropertiesSet() throws Exception {
User user = new User(1, "User");
User user1 = new User(2, "Admin");
User user2 = new User(3, "SuperAdmin");
listOfUsers.add(user);
listOfUsers.add(user1);
listOfUsers.add(user2);
System.out.println("-----------List of users added in init() method ------------");
for (Iterator < User > iterator = listOfUsers.iterator(); iterator.hasNext();) {
User user3 = (User) iterator.next();
System.out.println(user3.toString());
}
// save to database
}
@Override
public void destroy() {
// Delete from database
listOfUsers.clear();
System.out.println("-----------After of users removed from List in destroy() method ------------");
for (Iterator < User > iterator = listOfUsers.iterator(); iterator.hasNext();) {
User user3 = (User) iterator.next();
System.out.println(user3.toString());
}
System.out.println("List is clean up ..");
}
}
package com.demo.spring;
public class User {
private Integer id;
private String name;
public User() {}
public User(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
package com.demo.spring;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.demo.spring")
public class AppConfig {
}

注意:@ComponentScan注解扫描指定包中所有包中包含@Component注解的类,basePackages指定包路径。

package com.demo.spring;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
context.close();
}
}

Output:

-----------List of users added in init() method ------------
User [id=1, name=User]
User [id=2, name=Admin]
User [id=3, name=SuperAdmin]
-----------After of users removed from List in destroy() method -------
List is clean up ..
责任编辑:姜华 来源: 今日头条
相关推荐

2024-01-05 08:38:20

SpringBeanScope

2024-02-23 10:33:34

SpringBean容器

2022-06-07 07:58:45

SpringSpring AOP

2022-02-19 07:41:36

Bean注解项目

2022-05-30 09:32:07

Spring容器

2021-07-05 08:43:46

Spring Beanscope作用域

2022-06-08 08:04:28

Springservicerepository

2023-09-05 08:23:56

SpringScope方法

2022-07-20 07:32:46

Prototypevalue​容器

2020-10-14 06:23:54

SpringBean实例化

2022-03-14 08:54:42

SpringBean生命周期

2011-03-18 09:27:00

Spring

2022-06-09 07:27:14

JavaSpring容器

2022-05-30 11:17:44

Spring容器配置

2022-03-03 07:34:31

注解容器作用域

2021-03-08 08:40:25

Spring Bean 创建单例对象

2009-06-17 17:20:14

BeanFactorySpring

2009-06-17 17:04:37

BeanFactorySpring

2023-09-28 08:15:05

SpringBean加载

2020-06-10 07:38:30

Spring框架周期
点赞
收藏

51CTO技术栈公众号