Spring框架之Bean Scope

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 ..

文章标题:Spring框架之Bean Scope
网页网址:http://www.shufengxianlan.com/qtweb/news43/451643.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联