Spring源码解析-Scopes之Singleton Scope(单例)和Prototype Scope(多例)

本文深入探讨了Spring框架中Bean的作用域,重点解析了Singleton(单例)和Prototype(多例)两种最常见的作用域。Singleton是Spring的默认作用域,保证在每个IoC容器中只有一个实例。Prototype作用域则会在每次请求时创建一个新的实例。文章通过代码示例解释了两种作用域的创建方式、应用场景和注意事项,强调了在单例中避免使用有状态成员变量以防止多线程问题。
摘要由CSDN通过智能技术生成

Bean的作用域(scopes)

对于Spring里面的Bean的作用域(scope),我们在熟悉不过了,在Spring里面,平时开发中最经常遇到的作用域就是单例(singleton)和多例(prototype)了,但是除了单例和多例两个作用域,其实Spring还有其他的作用域,但是这些基本在开发中没用到过的,Spring完整的作用域有:
singleton:单例,spring默认的创建bean是个单例,在每个IOC容器里面只有唯一的实例;

prototype:多例,spring创建多例时,都会实例化一个新的实例,但是这些实例只有且仅有一个bean的定义对象;

request:将单个bean定义范围限定为单个HTTP请求的生命周期。每个HTTP请求都有自己的bean实例,它是在单个bean定义的后面创建的。仅在Web感知Spring的上下文中有效
ApplicationContext;

session:将单个bean定义范围限定为HTTP的生命周期Session。仅在Web感知Spring的上下文中有效ApplicationContext。

application:将单个bean定义到一个生命周期的范围ServletContext。仅在Web感知Spring的上下文中有效ApplicationContext。

websocket:将单个bean定义到一个生命周期的范围WebSocket。仅在Web感知Spring的上下文中有效ApplicationContext。

当然,除了spring定义的这些,我们自己也可以自定义scope。通过实现org.springframework.beans.factory.config.Scope这个接口来自定义我们的scope就可以了。

Singleton Scope(单例)

在spring的IOC容器中,一个单例bean有且仅有一个实例对象。也就是说,当你指定一个bean的定义为单例的话,spring IOC容器只会通过特定的bean定义创建唯一一个bean的实例对象,而这些被创建起来的单例会被缓存起来,在接下来的应用和请求中,都会返回缓存里的实例对象,spring关于单例的概念和我们平时在设计模式里面看到单例模式,还是有区别的,平时我们在设计模式书里面看到单例,往往是在每个类加载器上一个单例只会被实例化一次,即有且仅有一个实例对象,但是spring的单例更加侧着的是每个容器里只有一个实例化对象,所以这就要求容器的唯一性才能确保单例。 如何去指定一个bean是单例呢?spring提供了两种方式去实现,第一种,xml配置方式,通过xml来定义bean并指定scope;第二种,通过注解的方式,spring提供了注解@Scope来指定bean的作用域。

1.xml实现方式:

scope不指定默认就是单例,所以上面两种写法都是可以的。

2.注解实现方式

@Scope(value = “singleton”) @Service public class DefaultTestService {
}

通过以上两种方式创建出来的就是单例了。在spring中,我们大部分的类都是单例,在单例中,我们应该尽量不使用有状态的成员变量,单例的成员变量是共享的,这就会导致多线程问题,所以,我们的spring的controller和Struts的action这两种的实现是有差异的,因为spring的controller是单例的所以很少会用到类成员变量,而Struts跟前端交互的参数基本都是类成员变量,这是因为Struts的action是多例才能这样做。所以当我们在使用spring创建bean的时候,我们要慎用有状态的类成员变量,如果要使用必须同步操作,不然就会引起多线程共享变量的问题了。当然你也可以创建多例来解决多线程问题。 我们新建两个service类,这2个service类同时依赖了1个dao类,这个dao类有个变量count,初始化为0。下面看代码:

@Service public class DefaultTestService {
@Autowired
private TestDao testDao;

public Integer getCount() {
    return testDao.getCount();
}

public void IncCount() {
    testDao.setCount(testDao.getCount()+1);
}
public TestDao getTestDao() {
    return testDao;
}

public void setTestDao(TestDao testDao) {
    this.testDao = testDao;
} }

@Service public class DefaultTestService1 {
@Autowired
private TestDao testDao;

public Integer getCount() {
    return testDao.getCount();
}

public TestDao getTestDao() {
    return testDao;
}

public void setTestDao(TestDao testDao) {
    this.testDao = testDao;
} } @Component public class TestDao {

private Integer count =0;

public Integer getCount() {
    return count;
}

public void setCount(Integer count) {
    this.count = count;
} }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值