Spring Bean作用域(Scope)
Spring Doc: Bean Factory Scope
作用域 | 说明 |
---|---|
singleton | 默认Spring的作用域,一个beanFactory只有一个相应的实例 |
prototype | 原型作用域,每次依赖查找和依赖注入都会生成新的Spring bean对象 |
request | Spring bean存储在ServletRequest上下文中 |
session | bean存储在HTTPSession中 |
application | bean存储在ServletContext中 |
Singleton:
- 每次依赖查找或者依赖注入都为同一个对象
- 会执行Bena初始化方法回调@PostConstruct
- 会执行Bean销毁方法回调@PreDestroy
在一个应用中不一定是唯一的,只是在当前Spring IOC容器(BeanFactory)中是单例的,但是可能会有多个BeanFactory或者多层次BeanFactory
Prototype:
- 无论依赖注入还是依赖查找,都会生成一个新的对象
- 会执行Bean初始化方法回调@PostConstruct
不会
执行Bean销毁方法回调@PreDestroy- 注入集合时,prototype对象 != 直接注入的对象
注: 如果需要注入的对象每次调用都为新对象,则需要加上 @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
// 这样每次调用B类时,beanA都会为一个新的A类型的对象
@Service
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class A{
...
}
@Service
public class B{
@Autowired
private A beanA;
...
}
// 如果只是设置了scope=prototype,因为B和C都是单例(Spring默认单例),则只会在注入时生成一个新的对象,每次调用B\C类时,beanA都是和之前相同的,但是B.beanA != C.beanA,
@Service
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class A{
...
}
@Service
public class B{
@Autowired
private A beanA;
...
}
@Service
public class C{
@Autowired
private A beanA;
...
}
如果需要自定义Scope的作用域,可以参考org.springframework.context.support.SimpleThreadScope
@Override
public String getConversationId() {
return Thread.currentThread().getName();
// Thread 的名字是构造方法中传入的,是可以重复的,因此推荐Tread id
// Thread thread = Thread.currentThread();
// return String.valueOf(thread.getId());
}
然后使用
// {@link org.springframework.beans.factory.config.ConfigurableBeanFactory#registerScope}
configurableBeanFactory.addBeanFactoryPostProcessor(beanFactory -> {
// 注册自定义 scope
beanFactory.registerScope("MyScopeName", new SimpleThreadScope());
});
// 或者
@Bean
CustomScopeConfigurer customScopeConfigurer() {
CustomScopeConfigurer customScopeConfigurer = new CustomScopeConfigurer();
customScopeConfigurer.addScope("MyScopeName", new SimpleThreadScope());
return customScopeConfigurer;
}
@Scope(value = "MyScopeName")
Spring Cloud RefreshScope也是通过自定义bean的作用域来实现的