目录
Spring为我们提供的scope有: singleton,prototype,request,session,globalSession
1、singleton
2、prototype:每次调用新建一个Bean的实例
3、request: 给每一个http request新建一个Bean实例
4、session: 给每一个http session新建一个Bean实例。
5、globalSession:这个只在portal应用中有用,给每一个global http session新建一个Bean实例。
其中:
1、2是Spring自带的。3、4、5是Spring为我们自定义的。我也可以自定义Scope。
Scope注册
public class CustomScopeConfigurer implements BeanFactoryPostProcessor, BeanClassLoaderAware, Ordered:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (this.scopes != null) {
this.scopes.forEach((scopeKey, value) -> {
if (value instanceof Scope) {
beanFactory.registerScope(scopeKey, (Scope) value);
}
else if (value instanceof Class) {
Class<?> scopeClass = (Class<?>) value;
Assert.isAssignable(Scope.class, scopeClass, "Invalid scope class");
beanFactory.registerScope(scopeKey, (Scope) BeanUtils.instantiateClass(scopeClass));
}
else if (value instanceof String) {
Class<?> scopeClass = ClassUtils.resolveClassName((String) value, this.beanClassLoader);
Assert.isAssignable(Scope.class, scopeClass, "Invalid scope class");
beanFactory.registerScope(scopeKey, (Scope) BeanUtils.instantiateClass(scopeClass));
}
else {
throw new IllegalArgumentException("Mapped value [" + value + "] for scope key [" +
scopeKey + "] is not an instance of required type [" + Scope.class.getName() +
"] or a corresponding Class or String value indicating a Scope implementation");
}
});
}
}
AbstractBeanFactory#registerScope
public void registerScope(String scopeName, Scope scope) {
Assert.notNull(scopeName, "Scope identifier must not be null");
Assert.notNull(scope, "Scope must not be null");
if (SCOPE_SINGLETON.equals(scopeName) || SCOPE_PROTOTYPE.equals(scopeName)) {
throw new IllegalArgumentException("Cannot replace existing scopes 'singleton' and 'prototype'");
}
Scope previous = this.scopes.put(scopeName, scope);
if (previous != null && previous != scope) {
if (logger.isInfoEnabled()) {
logger.info("Replacing scope '" + scopeName + "' from [" + previous + "] to [" + scope + "]");
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Registering scope '" + scopeName + "' with implementation [" + scope + "]");
}
}
}
Scope创建
看下AbstractBeanFactory#doGetBean中scope创建是如何发起的
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 转化一下传入的beanName.如果是别名转真名,如果是&开头,去掉&。&代表取factoryBean
final String beanName = transformedBeanName(name);
Object bean;
// 1、这里为了解决Singleton循环依赖,如果允许早期暴露,会在这里取到其早期暴露,后面会介绍
// 2、如果是工厂模式,在获取bean的时候,在这里会先获取到factoryBean
Object sharedInstance = getSingleton(beanName);
// 如果 sharedInstance 不为空,说明当前singleton是依赖者在注入属性时创建的。则打印相关日志
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 这里会将name和beanName同时传进来, 因为一开始我们的name可能是带&符号的,代表这里需要获取factoryBean而不是bean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 判断是否有父容器,如果有父容器,优先用父容器调用其getBean
BeanFactory parentBeanFactory = get